mirror of
https://github.com/roc-lang/roc.git
synced 2025-08-03 03:42:17 +00:00
Progress on updating entire compiler for snake_case
This commit is contained in:
parent
db6cc5a7b1
commit
b56fbd38e1
297 changed files with 8416 additions and 8544 deletions
|
@ -1,107 +1,107 @@
|
|||
module [findPath, Model, initialModel, cheapestOpen, reconstructPath]
|
||||
module [find_path, Model, initial_model, cheapest_open, reconstruct_path]
|
||||
|
||||
import Quicksort
|
||||
|
||||
findPath = \costFn, moveFn, start, end ->
|
||||
astar costFn moveFn end (initialModel start)
|
||||
find_path = \cost_fn, move_fn, start, end ->
|
||||
astar(cost_fn, move_fn, end, initial_model(start))
|
||||
|
||||
Model position : {
|
||||
evaluated : Set position,
|
||||
openSet : Set position,
|
||||
open_set : Set position,
|
||||
costs : Dict position F64,
|
||||
cameFrom : Dict position position,
|
||||
came_from : Dict position position,
|
||||
} where position implements Hash & Eq
|
||||
|
||||
initialModel : position -> Model position where position implements Hash & Eq
|
||||
initialModel = \start -> {
|
||||
evaluated: Set.empty {},
|
||||
openSet: Set.single start,
|
||||
costs: Dict.single start 0,
|
||||
cameFrom: Dict.empty {},
|
||||
initial_model : position -> Model position where position implements Hash & Eq
|
||||
initial_model = \start -> {
|
||||
evaluated: Set.empty({}),
|
||||
open_set: Set.single(start),
|
||||
costs: Dict.single(start, 0),
|
||||
came_from: Dict.empty({}),
|
||||
}
|
||||
|
||||
cheapestOpen : (position -> F64), Model position -> Result position {} where position implements Hash & Eq
|
||||
cheapestOpen = \costFn, model ->
|
||||
model.openSet
|
||||
|> Set.toList
|
||||
|> List.keepOks
|
||||
(\position ->
|
||||
when Dict.get model.costs position is
|
||||
Err _ -> Err {}
|
||||
Ok cost -> Ok { cost: cost + costFn position, position }
|
||||
)
|
||||
|> Quicksort.sortBy .cost
|
||||
cheapest_open : (position -> F64), Model position -> Result position {} where position implements Hash & Eq
|
||||
cheapest_open = \cost_fn, model ->
|
||||
model.open_set
|
||||
|> Set.to_list
|
||||
|> List.keep_oks(
|
||||
\position ->
|
||||
when Dict.get(model.costs, position) is
|
||||
Err(_) -> Err({})
|
||||
Ok(cost) -> Ok({ cost: cost + cost_fn(position), position }),
|
||||
)
|
||||
|> Quicksort.sort_by(.cost)
|
||||
|> List.first
|
||||
|> Result.map .position
|
||||
|> Result.mapErr (\_ -> {})
|
||||
|> Result.map(.position)
|
||||
|> Result.map_err(\_ -> {})
|
||||
|
||||
reconstructPath : Dict position position, position -> List position where position implements Hash & Eq
|
||||
reconstructPath = \cameFrom, goal ->
|
||||
when Dict.get cameFrom goal is
|
||||
Err _ -> []
|
||||
Ok next -> List.append (reconstructPath cameFrom next) goal
|
||||
reconstruct_path : Dict position position, position -> List position where position implements Hash & Eq
|
||||
reconstruct_path = \came_from, goal ->
|
||||
when Dict.get(came_from, goal) is
|
||||
Err(_) -> []
|
||||
Ok(next) -> List.append(reconstruct_path(came_from, next), goal)
|
||||
|
||||
updateCost : position, position, Model position -> Model position where position implements Hash & Eq
|
||||
updateCost = \current, neighbor, model ->
|
||||
newCameFrom =
|
||||
Dict.insert model.cameFrom neighbor current
|
||||
update_cost : position, position, Model position -> Model position where position implements Hash & Eq
|
||||
update_cost = \current, neighbor, model ->
|
||||
new_came_from =
|
||||
Dict.insert(model.came_from, neighbor, current)
|
||||
|
||||
newCosts =
|
||||
Dict.insert model.costs neighbor distanceTo
|
||||
new_costs =
|
||||
Dict.insert(model.costs, neighbor, distance_to)
|
||||
|
||||
distanceTo =
|
||||
reconstructPath newCameFrom neighbor
|
||||
distance_to =
|
||||
reconstruct_path(new_came_from, neighbor)
|
||||
|> List.len
|
||||
|> Num.toFrac
|
||||
|> Num.to_frac
|
||||
|
||||
newModel =
|
||||
new_model =
|
||||
{ model &
|
||||
costs: newCosts,
|
||||
cameFrom: newCameFrom,
|
||||
costs: new_costs,
|
||||
came_from: new_came_from,
|
||||
}
|
||||
|
||||
when Dict.get model.costs neighbor is
|
||||
Err _ ->
|
||||
newModel
|
||||
when Dict.get(model.costs, neighbor) is
|
||||
Err(_) ->
|
||||
new_model
|
||||
|
||||
Ok previousDistance ->
|
||||
if distanceTo < previousDistance then
|
||||
newModel
|
||||
Ok(previous_distance) ->
|
||||
if distance_to < previous_distance then
|
||||
new_model
|
||||
else
|
||||
model
|
||||
|
||||
astar : (position, position -> F64), (position -> Set position), position, Model position -> Result (List position) {} where position implements Hash & Eq
|
||||
astar = \costFn, moveFn, goal, model ->
|
||||
when cheapestOpen (\source -> costFn source goal) model is
|
||||
Err {} -> Err {}
|
||||
Ok current ->
|
||||
astar = \cost_fn, move_fn, goal, model ->
|
||||
when cheapest_open(\source -> cost_fn(source, goal), model) is
|
||||
Err({}) -> Err({})
|
||||
Ok(current) ->
|
||||
if current == goal then
|
||||
Ok (reconstructPath model.cameFrom goal)
|
||||
Ok(reconstruct_path(model.came_from, goal))
|
||||
else
|
||||
modelPopped =
|
||||
model_popped =
|
||||
{ model &
|
||||
openSet: Set.remove model.openSet current,
|
||||
evaluated: Set.insert model.evaluated current,
|
||||
open_set: Set.remove(model.open_set, current),
|
||||
evaluated: Set.insert(model.evaluated, current),
|
||||
}
|
||||
|
||||
neighbors =
|
||||
moveFn current
|
||||
move_fn(current)
|
||||
|
||||
newNeighbors =
|
||||
Set.difference neighbors modelPopped.evaluated
|
||||
new_neighbors =
|
||||
Set.difference(neighbors, model_popped.evaluated)
|
||||
|
||||
modelWithNeighbors : Model position
|
||||
modelWithNeighbors =
|
||||
modelPopped
|
||||
|> &openSet (Set.union modelPopped.openSet newNeighbors)
|
||||
model_with_neighbors : Model position
|
||||
model_with_neighbors =
|
||||
model_popped
|
||||
|> &open_set(Set.union(model_popped.open_set, new_neighbors))
|
||||
|
||||
walker : Model position, position -> Model position
|
||||
walker = \amodel, n -> updateCost current n amodel
|
||||
walker = \amodel, n -> update_cost(current, n, amodel)
|
||||
|
||||
modelWithCosts =
|
||||
Set.walk newNeighbors modelWithNeighbors walker
|
||||
model_with_costs =
|
||||
Set.walk(new_neighbors, model_with_neighbors, walker)
|
||||
|
||||
astar costFn moveFn goal modelWithCosts
|
||||
astar(cost_fn, move_fn, goal, model_with_costs)
|
||||
|
||||
# takeStep = \moveFn, _goal, model, current ->
|
||||
# modelPopped =
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
module [fromBytes, fromStr, toBytes, toStr]
|
||||
module [from_bytes, from_str, to_bytes, to_str]
|
||||
|
||||
import Base64.Decode
|
||||
import Base64.Encode
|
||||
|
||||
# base 64 encoding from a sequence of bytes
|
||||
fromBytes : List U8 -> Result Str [InvalidInput]
|
||||
fromBytes = \bytes ->
|
||||
when Base64.Decode.fromBytes bytes is
|
||||
Ok v ->
|
||||
Ok v
|
||||
from_bytes : List U8 -> Result Str [InvalidInput]
|
||||
from_bytes = \bytes ->
|
||||
when Base64.Decode.from_bytes(bytes) is
|
||||
Ok(v) ->
|
||||
Ok(v)
|
||||
|
||||
Err _ ->
|
||||
Err InvalidInput
|
||||
Err(_) ->
|
||||
Err(InvalidInput)
|
||||
|
||||
# base 64 encoding from a string
|
||||
fromStr : Str -> Result Str [InvalidInput]
|
||||
fromStr = \str ->
|
||||
fromBytes (Str.toUtf8 str)
|
||||
from_str : Str -> Result Str [InvalidInput]
|
||||
from_str = \str ->
|
||||
from_bytes(Str.to_utf8(str))
|
||||
|
||||
# base64-encode bytes to the original
|
||||
toBytes : Str -> Result (List U8) [InvalidInput]
|
||||
toBytes = \str ->
|
||||
Ok (Base64.Encode.toBytes str)
|
||||
to_bytes : Str -> Result (List U8) [InvalidInput]
|
||||
to_bytes = \str ->
|
||||
Ok(Base64.Encode.to_bytes(str))
|
||||
|
||||
toStr : Str -> Result Str [InvalidInput]
|
||||
toStr = \str ->
|
||||
when toBytes str is
|
||||
Ok bytes ->
|
||||
when Str.fromUtf8 bytes is
|
||||
Ok v ->
|
||||
Ok v
|
||||
to_str : Str -> Result Str [InvalidInput]
|
||||
to_str = \str ->
|
||||
when to_bytes(str) is
|
||||
Ok(bytes) ->
|
||||
when Str.from_utf8(bytes) is
|
||||
Ok(v) ->
|
||||
Ok(v)
|
||||
|
||||
Err _ ->
|
||||
Err InvalidInput
|
||||
Err(_) ->
|
||||
Err(InvalidInput)
|
||||
|
||||
Err _ ->
|
||||
Err InvalidInput
|
||||
Err(_) ->
|
||||
Err(InvalidInput)
|
||||
|
|
|
@ -1,86 +1,86 @@
|
|||
module [fromBytes]
|
||||
module [from_bytes]
|
||||
|
||||
import Bytes.Decode exposing [ByteDecoder, DecodeProblem]
|
||||
|
||||
fromBytes : List U8 -> Result Str DecodeProblem
|
||||
fromBytes = \bytes ->
|
||||
Bytes.Decode.decode bytes (decodeBase64 (List.len bytes))
|
||||
from_bytes : List U8 -> Result Str DecodeProblem
|
||||
from_bytes = \bytes ->
|
||||
Bytes.Decode.decode(bytes, decode_base64(List.len(bytes)))
|
||||
|
||||
decodeBase64 : U64 -> ByteDecoder Str
|
||||
decodeBase64 = \width -> Bytes.Decode.loop loopHelp { remaining: width, string: "" }
|
||||
decode_base64 : U64 -> ByteDecoder Str
|
||||
decode_base64 = \width -> Bytes.Decode.loop(loop_help, { remaining: width, string: "" })
|
||||
|
||||
loopHelp : { remaining : U64, string : Str } -> ByteDecoder (Bytes.Decode.Step { remaining : U64, string : Str } Str)
|
||||
loopHelp = \{ remaining, string } ->
|
||||
loop_help : { remaining : U64, string : Str } -> ByteDecoder (Bytes.Decode.Step { remaining : U64, string : Str } Str)
|
||||
loop_help = \{ remaining, string } ->
|
||||
if remaining >= 3 then
|
||||
Bytes.Decode.map3 Bytes.Decode.u8 Bytes.Decode.u8 Bytes.Decode.u8 \x, y, z ->
|
||||
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 {
|
||||
Loop({
|
||||
remaining: remaining - 3,
|
||||
string: Str.concat string (bitsToChars combined 0),
|
||||
}
|
||||
string: Str.concat(string, bits_to_chars(combined, 0)),
|
||||
}))
|
||||
else if remaining == 0 then
|
||||
Bytes.Decode.succeed (Done string)
|
||||
Bytes.Decode.succeed(Done(string))
|
||||
else if remaining == 2 then
|
||||
Bytes.Decode.map2 Bytes.Decode.u8 Bytes.Decode.u8 \x, y ->
|
||||
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 (bitsToChars combined 1))
|
||||
Done(Str.concat(string, bits_to_chars(combined, 1))))
|
||||
else
|
||||
# remaining = 1
|
||||
Bytes.Decode.map Bytes.Decode.u8 \x ->
|
||||
Bytes.Decode.map(Bytes.Decode.u8, \x ->
|
||||
|
||||
a : U32
|
||||
a = Num.intCast x
|
||||
a = Num.int_cast(x)
|
||||
|
||||
Done (Str.concat string (bitsToChars (Num.shiftLeftBy a 16) 2))
|
||||
Done(Str.concat(string, bits_to_chars(Num.shift_left_by(a, 16), 2))))
|
||||
|
||||
bitsToChars : U32, Int * -> Str
|
||||
bitsToChars = \bits, missing ->
|
||||
when Str.fromUtf8 (bitsToCharsHelp bits missing) is
|
||||
Ok str -> str
|
||||
Err _ -> ""
|
||||
bits_to_chars : U32, Int * -> Str
|
||||
bits_to_chars = \bits, missing ->
|
||||
when Str.from_utf8(bits_to_chars_help(bits, missing)) is
|
||||
Ok(str) -> str
|
||||
Err(_) -> ""
|
||||
|
||||
# Mask that can be used to get the lowest 6 bits of a binary number
|
||||
lowest6BitsMask : Int *
|
||||
lowest6BitsMask = 63
|
||||
lowest6_bits_mask : Int *
|
||||
lowest6_bits_mask = 63
|
||||
|
||||
bitsToCharsHelp : U32, Int * -> List U8
|
||||
bitsToCharsHelp = \bits, missing ->
|
||||
bits_to_chars_help : U32, Int * -> List U8
|
||||
bits_to_chars_help = \bits, missing ->
|
||||
# The input is 24 bits, which we have to partition into 4 6-bit segments. We achieve this by
|
||||
# shifting to the right by (a multiple of) 6 to remove unwanted bits on the right, then `Num.bitwiseAnd`
|
||||
# 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
|
||||
|> unsafeToChar
|
||||
Num.shift_right_zf_by(bits, 18)
|
||||
|> Num.int_cast
|
||||
|> unsafe_to_char
|
||||
|
||||
q =
|
||||
Num.bitwiseAnd (Num.shiftRightZfBy bits 12) lowest6BitsMask
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
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) lowest6BitsMask
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
Num.bitwise_and(Num.shift_right_zf_by(bits, 6), lowest6_bits_mask)
|
||||
|> Num.int_cast
|
||||
|> unsafe_to_char
|
||||
|
||||
s =
|
||||
Num.bitwiseAnd bits lowest6BitsMask
|
||||
|> Num.intCast
|
||||
|> unsafeToChar
|
||||
Num.bitwise_and(bits, lowest6_bits_mask)
|
||||
|> Num.int_cast
|
||||
|> unsafe_to_char
|
||||
|
||||
equals : U8
|
||||
equals = 61
|
||||
|
@ -94,8 +94,8 @@ bitsToCharsHelp = \bits, missing ->
|
|||
[]
|
||||
|
||||
# Base64 index to character/digit
|
||||
unsafeToChar : U8 -> U8
|
||||
unsafeToChar = \n ->
|
||||
unsafe_to_char : U8 -> U8
|
||||
unsafe_to_char = \n ->
|
||||
if n <= 25 then
|
||||
# uppercase characters
|
||||
65 + n
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
module [toBytes]
|
||||
module [to_bytes]
|
||||
|
||||
import Bytes.Encode exposing [ByteEncoder]
|
||||
|
||||
InvalidChar : U8
|
||||
|
||||
# State : [None, One U8, Two U8, Three U8]
|
||||
toBytes : Str -> List U8
|
||||
toBytes = \str ->
|
||||
to_bytes : Str -> List U8
|
||||
to_bytes = \str ->
|
||||
str
|
||||
|> Str.toUtf8
|
||||
|> encodeChunks
|
||||
|> Str.to_utf8
|
||||
|> encode_chunks
|
||||
|> Bytes.Encode.sequence
|
||||
|> Bytes.Encode.encode
|
||||
|
||||
encodeChunks : List U8 -> List ByteEncoder
|
||||
encodeChunks = \bytes ->
|
||||
List.walk bytes { output: [], accum: None } folder
|
||||
|> encodeResidual
|
||||
encode_chunks : List U8 -> List ByteEncoder
|
||||
encode_chunks = \bytes ->
|
||||
List.walk(bytes, { output: [], accum: None }, folder)
|
||||
|> encode_residual
|
||||
|
||||
coerce : U64, a -> a
|
||||
coerce = \_, x -> x
|
||||
|
@ -24,113 +24,114 @@ coerce = \_, x -> x
|
|||
# folder : { output : List ByteEncoder, accum : State }, U8 -> { output : List ByteEncoder, accum : State }
|
||||
folder = \{ output, accum }, char ->
|
||||
when accum is
|
||||
Unreachable n -> coerce n { output, accum: Unreachable n }
|
||||
None -> { output, accum: One char }
|
||||
One a -> { output, accum: Two a char }
|
||||
Two a b -> { output, accum: Three a b char }
|
||||
Three a b c ->
|
||||
when encodeCharacters a b c char is
|
||||
Ok encoder ->
|
||||
Unreachable(n) -> coerce(n, { output, accum: Unreachable(n) })
|
||||
None -> { output, accum: One(char) }
|
||||
One(a) -> { output, accum: Two(a, char) }
|
||||
Two(a, b) -> { output, accum: Three(a, b, char) }
|
||||
Three(a, b, c) ->
|
||||
when encode_characters(a, b, c, char) is
|
||||
Ok(encoder) ->
|
||||
{
|
||||
output: List.append output encoder,
|
||||
output: List.append(output, encoder),
|
||||
accum: None,
|
||||
}
|
||||
|
||||
Err _ ->
|
||||
Err(_) ->
|
||||
{ output, accum: None }
|
||||
|
||||
# SGVs bG8g V29y bGQ=
|
||||
# encodeResidual : { output : List ByteEncoder, accum : State } -> List ByteEncoder
|
||||
encodeResidual = \{ output, accum } ->
|
||||
encode_residual = \{ output, accum } ->
|
||||
when accum is
|
||||
Unreachable _ -> output
|
||||
Unreachable(_) -> output
|
||||
None -> output
|
||||
One _ -> output
|
||||
Two a b ->
|
||||
when encodeCharacters a b equals equals is
|
||||
Ok encoder -> List.append output encoder
|
||||
Err _ -> output
|
||||
One(_) -> output
|
||||
Two(a, b) ->
|
||||
when encode_characters(a, b, equals, equals) is
|
||||
Ok(encoder) -> List.append(output, encoder)
|
||||
Err(_) -> output
|
||||
|
||||
Three a b c ->
|
||||
when encodeCharacters a b c equals is
|
||||
Ok encoder -> List.append output encoder
|
||||
Err _ -> output
|
||||
Three(a, b, c) ->
|
||||
when encode_characters(a, b, c, equals) is
|
||||
Ok(encoder) -> List.append(output, encoder)
|
||||
Err(_) -> output
|
||||
|
||||
equals : U8
|
||||
equals = 61
|
||||
|
||||
# Convert 4 characters to 24 bits (as an ByteEncoder)
|
||||
encodeCharacters : U8, U8, U8, U8 -> Result ByteEncoder InvalidChar
|
||||
encodeCharacters = \a, b, c, d ->
|
||||
if !(isValidChar a) then
|
||||
Err a
|
||||
else if !(isValidChar b) then
|
||||
Err b
|
||||
encode_characters : U8, U8, U8, U8 -> Result ByteEncoder InvalidChar
|
||||
encode_characters = \a, b, c, d ->
|
||||
if !(is_valid_char(a)) then
|
||||
Err(a)
|
||||
else if !(is_valid_char(b)) then
|
||||
Err(b)
|
||||
else
|
||||
# `=` is the padding character, and must be special-cased
|
||||
# only the `c` and `d` char are allowed to be padding
|
||||
n1 = unsafeConvertChar a
|
||||
n2 = unsafeConvertChar b
|
||||
n1 = unsafe_convert_char(a)
|
||||
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 !(isValidChar c) then
|
||||
Err c
|
||||
Ok(Bytes.Encode.u8(b1))
|
||||
else if !(is_valid_char(c)) then
|
||||
Err(c)
|
||||
else
|
||||
n3 = unsafeConvertChar c
|
||||
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 !(isValidChar d) then
|
||||
Err d
|
||||
Ok(Bytes.Encode.u16(BE, combined))
|
||||
else if !(is_valid_char(d)) then
|
||||
Err(d)
|
||||
else
|
||||
n3 = unsafeConvertChar c
|
||||
n4 = unsafeConvertChar d
|
||||
n3 = unsafe_convert_char(c)
|
||||
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])
|
||||
Ok(Bytes.Encode.sequence([Bytes.Encode.u16(BE, combined), Bytes.Encode.u8(b3)]))
|
||||
|
||||
# is the character a base64 digit?
|
||||
# The base16 digits are: A-Z, a-z, 0-1, '+' and '/'
|
||||
isValidChar : U8 -> Bool
|
||||
isValidChar = \c ->
|
||||
if isAlphaNum c then
|
||||
is_valid_char : U8 -> Bool
|
||||
is_valid_char = \c ->
|
||||
if is_alpha_num(c) then
|
||||
Bool.true
|
||||
else
|
||||
when c is
|
||||
|
@ -145,14 +146,14 @@ isValidChar = \c ->
|
|||
_ ->
|
||||
Bool.false
|
||||
|
||||
isAlphaNum : U8 -> Bool
|
||||
isAlphaNum = \key ->
|
||||
is_alpha_num : U8 -> Bool
|
||||
is_alpha_num = \key ->
|
||||
(key >= 48 && key <= 57) || (key >= 64 && key <= 90) || (key >= 97 && key <= 122)
|
||||
|
||||
# Convert a base64 character/digit to its index
|
||||
# See also [Wikipedia](https://en.wikipedia.org/wiki/Base64#Base64_table)
|
||||
unsafeConvertChar : U8 -> U8
|
||||
unsafeConvertChar = \key ->
|
||||
unsafe_convert_char : U8 -> U8
|
||||
unsafe_convert_char = \key ->
|
||||
if key >= 65 && key <= 90 then
|
||||
# A-Z
|
||||
key - 65
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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),
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
module [text, asText]
|
||||
module [text, as_text]
|
||||
|
||||
text = "Hello, world!"
|
||||
|
||||
asText = Num.toStr
|
||||
as_text = Num.to_str
|
||||
|
|
|
@ -1,75 +1,75 @@
|
|||
module [sortBy, sortWith, show]
|
||||
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)]"
|
||||
|
||||
sortBy : List a, (a -> Num *) -> List a
|
||||
sortBy = \list, toComparable ->
|
||||
sortWith list (\x, y -> Num.compare (toComparable x) (toComparable y))
|
||||
sort_by : List a, (a -> Num *) -> List a
|
||||
sort_by = \list, to_comparable ->
|
||||
sort_with(list, \x, y -> Num.compare(to_comparable(x), to_comparable(y)))
|
||||
|
||||
Order a : a, a -> [LT, GT, EQ]
|
||||
|
||||
sortWith : List a, (a, a -> [LT, GT, EQ]) -> List a
|
||||
sortWith = \list, order ->
|
||||
n = List.len list
|
||||
sort_with : List a, (a, a -> [LT, GT, EQ]) -> List a
|
||||
sort_with = \list, order ->
|
||||
n = List.len(list)
|
||||
|
||||
quicksortHelp list order 0 (n - 1)
|
||||
quicksort_help(list, order, 0, (n - 1))
|
||||
|
||||
quicksortHelp : List a, Order a, U64, U64 -> List a
|
||||
quicksortHelp = \list, order, low, high ->
|
||||
quicksort_help : List a, Order a, U64, U64 -> List a
|
||||
quicksort_help = \list, order, low, high ->
|
||||
if low < high then
|
||||
when partition low high list order is
|
||||
Pair partitionIndex partitioned ->
|
||||
when partition(low, high, list, order) is
|
||||
Pair(partition_index, partitioned) ->
|
||||
partitioned
|
||||
|> quicksortHelp order low (Num.subSaturated partitionIndex 1)
|
||||
|> quicksortHelp order (partitionIndex + 1) high
|
||||
|> quicksort_help(order, low, Num.sub_saturated(partition_index, 1))
|
||||
|> quicksort_help(order, (partition_index + 1), high)
|
||||
else
|
||||
list
|
||||
|
||||
partition : U64, U64, List a, Order a -> [Pair U64 (List a)]
|
||||
partition = \low, high, initialList, order ->
|
||||
when List.get initialList high is
|
||||
Ok pivot ->
|
||||
when partitionHelp low low initialList order high pivot is
|
||||
Pair newI newList ->
|
||||
Pair newI (swap newI high newList)
|
||||
partition = \low, high, initial_list, order ->
|
||||
when List.get(initial_list, high) is
|
||||
Ok(pivot) ->
|
||||
when partition_help(low, low, initial_list, order, 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 c, Order c, U64, c -> [Pair U64 (List c)]
|
||||
partitionHelp = \i, j, list, order, high, pivot ->
|
||||
partition_help : U64, U64, List c, Order c, U64, c -> [Pair U64 (List c)]
|
||||
partition_help = \i, j, list, order, high, pivot ->
|
||||
if j < high then
|
||||
when List.get list j is
|
||||
Ok value ->
|
||||
when order value pivot is
|
||||
when List.get(list, j) is
|
||||
Ok(value) ->
|
||||
when order(value, pivot) is
|
||||
LT | EQ ->
|
||||
partitionHelp (i + 1) (j + 1) (swap i j list) order high pivot
|
||||
partition_help((i + 1), (j + 1), swap(i, j, list), order, high, pivot)
|
||||
|
||||
GT ->
|
||||
partitionHelp i (j + 1) list order high pivot
|
||||
partition_help(i, (j + 1), list, order, 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)
|
||||
|
||||
_ ->
|
||||
[]
|
||||
|
|
|
@ -5,27 +5,27 @@ import pf.PlatformTasks
|
|||
# adapted from https://github.com/koka-lang/koka/blob/master/test/bench/haskell/cfold.hs
|
||||
main : Task {} []
|
||||
main =
|
||||
{ value, isError } = PlatformTasks.getInt!
|
||||
inputResult =
|
||||
if isError then
|
||||
Err GetIntError
|
||||
{ value, is_error } = PlatformTasks.get_int!
|
||||
input_result =
|
||||
if is_error then
|
||||
Err(GetIntError)
|
||||
else
|
||||
Ok value
|
||||
Ok(value)
|
||||
|
||||
when inputResult is
|
||||
Ok n ->
|
||||
e = mkExpr n 1 # original koka n = 20 (set `ulimit -s unlimited` to avoid stack overflow for n = 20)
|
||||
unoptimized = eval e
|
||||
optimized = eval (constFolding (reassoc e))
|
||||
when input_result is
|
||||
Ok(n) ->
|
||||
e = mk_expr(n, 1) # original koka n = 20 (set `ulimit -s unlimited` to avoid stack overflow for n = 20)
|
||||
unoptimized = eval(e)
|
||||
optimized = eval(const_folding(reassoc(e)))
|
||||
|
||||
unoptimized
|
||||
|> Num.toStr
|
||||
|> Str.concat " & "
|
||||
|> Str.concat (Num.toStr optimized)
|
||||
|> PlatformTasks.putLine
|
||||
|> Num.to_str
|
||||
|> Str.concat(" & ")
|
||||
|> Str.concat(Num.to_str(optimized))
|
||||
|> PlatformTasks.put_line
|
||||
|
||||
Err GetIntError ->
|
||||
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||
Err(GetIntError) ->
|
||||
PlatformTasks.put_line("Error: Failed to get Integer from stdin.")
|
||||
|
||||
Expr : [
|
||||
Add Expr Expr,
|
||||
|
@ -34,97 +34,97 @@ Expr : [
|
|||
Var I64,
|
||||
]
|
||||
|
||||
mkExpr : I64, I64 -> Expr
|
||||
mkExpr = \n, v ->
|
||||
mk_expr : I64, I64 -> Expr
|
||||
mk_expr = \n, v ->
|
||||
when n is
|
||||
0 ->
|
||||
if v == 0 then Var 1 else Val v
|
||||
if v == 0 then Var(1) else Val(v)
|
||||
|
||||
_ ->
|
||||
Add (mkExpr (n - 1) (v + 1)) (mkExpr (n - 1) (max (v - 1) 0))
|
||||
Add(mk_expr((n - 1), (v + 1)), mk_expr((n - 1), max((v - 1), 0)))
|
||||
|
||||
max : I64, I64 -> I64
|
||||
max = \a, b -> if a > b then a else b
|
||||
|
||||
appendAdd : Expr, Expr -> Expr
|
||||
appendAdd = \e1, e2 ->
|
||||
append_add : Expr, Expr -> Expr
|
||||
append_add = \e1, e2 ->
|
||||
when e1 is
|
||||
Add a1 a2 ->
|
||||
Add a1 (appendAdd a2 e2)
|
||||
Add(a1, a2) ->
|
||||
Add(a1, append_add(a2, e2))
|
||||
|
||||
_ ->
|
||||
Add e1 e2
|
||||
Add(e1, e2)
|
||||
|
||||
appendMul : Expr, Expr -> Expr
|
||||
appendMul = \e1, e2 ->
|
||||
append_mul : Expr, Expr -> Expr
|
||||
append_mul = \e1, e2 ->
|
||||
when e1 is
|
||||
Mul a1 a2 ->
|
||||
Mul a1 (appendMul a2 e2)
|
||||
Mul(a1, a2) ->
|
||||
Mul(a1, append_mul(a2, e2))
|
||||
|
||||
_ ->
|
||||
Mul e1 e2
|
||||
Mul(e1, e2)
|
||||
|
||||
eval : Expr -> I64
|
||||
eval = \e ->
|
||||
when e is
|
||||
Var _ ->
|
||||
Var(_) ->
|
||||
0
|
||||
|
||||
Val v ->
|
||||
Val(v) ->
|
||||
v
|
||||
|
||||
Add l r ->
|
||||
eval l + eval r
|
||||
Add(l, r) ->
|
||||
eval(l) + eval(r)
|
||||
|
||||
Mul l r ->
|
||||
eval l * eval r
|
||||
Mul(l, r) ->
|
||||
eval(l) * eval(r)
|
||||
|
||||
reassoc : Expr -> Expr
|
||||
reassoc = \e ->
|
||||
when e is
|
||||
Add e1 e2 ->
|
||||
x1 = reassoc e1
|
||||
x2 = reassoc e2
|
||||
Add(e1, e2) ->
|
||||
x1 = reassoc(e1)
|
||||
x2 = reassoc(e2)
|
||||
|
||||
appendAdd x1 x2
|
||||
append_add(x1, x2)
|
||||
|
||||
Mul e1 e2 ->
|
||||
x1 = reassoc e1
|
||||
x2 = reassoc e2
|
||||
Mul(e1, e2) ->
|
||||
x1 = reassoc(e1)
|
||||
x2 = reassoc(e2)
|
||||
|
||||
appendMul x1 x2
|
||||
append_mul(x1, x2)
|
||||
|
||||
_ ->
|
||||
e
|
||||
|
||||
constFolding : Expr -> Expr
|
||||
constFolding = \e ->
|
||||
const_folding : Expr -> Expr
|
||||
const_folding = \e ->
|
||||
when e is
|
||||
Add e1 e2 ->
|
||||
x1 = constFolding e1
|
||||
x2 = constFolding e2
|
||||
Add(e1, e2) ->
|
||||
x1 = const_folding(e1)
|
||||
x2 = const_folding(e2)
|
||||
|
||||
when x1 is
|
||||
Val a ->
|
||||
Val(a) ->
|
||||
when x2 is
|
||||
Val b -> Val (a + b)
|
||||
Add (Val b) x | Add x (Val b) -> Add (Val (a + b)) x
|
||||
_ -> Add x1 x2
|
||||
Val(b) -> Val((a + b))
|
||||
Add(Val(b), x) | Add(x, Val(b)) -> Add(Val((a + b)), x)
|
||||
_ -> Add(x1, x2)
|
||||
|
||||
_ -> Add x1 x2
|
||||
_ -> Add(x1, x2)
|
||||
|
||||
Mul e1 e2 ->
|
||||
x1 = constFolding e1
|
||||
x2 = constFolding e2
|
||||
Mul(e1, e2) ->
|
||||
x1 = const_folding(e1)
|
||||
x2 = const_folding(e2)
|
||||
|
||||
when x1 is
|
||||
Val a ->
|
||||
Val(a) ->
|
||||
when x2 is
|
||||
Val b -> Val (a * b)
|
||||
Mul (Val b) x | Mul x (Val b) -> Mul (Val (a * b)) x
|
||||
_ -> Mul x1 x2
|
||||
Val(b) -> Val((a * b))
|
||||
Mul(Val(b), x) | Mul(x, Val(b)) -> Mul(Val((a * b)), x)
|
||||
_ -> Mul(x1, x2)
|
||||
|
||||
_ -> Mul x1 x2
|
||||
_ -> Mul(x1, x2)
|
||||
|
||||
_ ->
|
||||
e
|
||||
|
|
|
@ -2,19 +2,19 @@ app [main] { pf: platform "platform/main.roc" }
|
|||
|
||||
main : Task {} []
|
||||
main =
|
||||
closure1 {}
|
||||
|> Task.await (\_ -> closure2 {})
|
||||
|> Task.await (\_ -> closure3 {})
|
||||
|> Task.await (\_ -> closure4 {})
|
||||
closure1({})
|
||||
|> Task.await(\_ -> closure2({}))
|
||||
|> Task.await(\_ -> closure3({}))
|
||||
|> Task.await(\_ -> closure4({}))
|
||||
# ---
|
||||
closure1 : {} -> Task {} []
|
||||
closure1 = \_ ->
|
||||
Task.ok (foo toUnitBorrowed "a long string such that it's malloced")
|
||||
|> Task.map \_ -> {}
|
||||
Task.ok(foo(to_unit_borrowed, "a long string such that it's malloced"))
|
||||
|> Task.map(\_ -> {})
|
||||
|
||||
toUnitBorrowed = \x -> Str.countUtf8Bytes x
|
||||
to_unit_borrowed = \x -> Str.count_utf8_bytes(x)
|
||||
|
||||
foo = \f, x -> f x
|
||||
foo = \f, x -> f(x)
|
||||
|
||||
# ---
|
||||
closure2 : {} -> Task {} []
|
||||
|
@ -22,11 +22,11 @@ closure2 = \_ ->
|
|||
x : Str
|
||||
x = "a long string such that it's malloced"
|
||||
|
||||
Task.ok {}
|
||||
|> Task.map (\_ -> x)
|
||||
|> Task.map toUnit
|
||||
Task.ok({})
|
||||
|> Task.map(\_ -> x)
|
||||
|> Task.map(to_unit)
|
||||
|
||||
toUnit = \_ -> {}
|
||||
to_unit = \_ -> {}
|
||||
|
||||
# # ---
|
||||
closure3 : {} -> Task {} []
|
||||
|
@ -34,8 +34,8 @@ closure3 = \_ ->
|
|||
x : Str
|
||||
x = "a long string such that it's malloced"
|
||||
|
||||
Task.ok {}
|
||||
|> Task.await (\_ -> Task.ok x |> Task.map (\_ -> {}))
|
||||
Task.ok({})
|
||||
|> Task.await(\_ -> Task.ok(x) |> Task.map(\_ -> {}))
|
||||
|
||||
# # ---
|
||||
closure4 : {} -> Task {} []
|
||||
|
@ -43,6 +43,6 @@ closure4 = \_ ->
|
|||
x : Str
|
||||
x = "a long string such that it's malloced"
|
||||
|
||||
Task.ok {}
|
||||
|> Task.await (\_ -> Task.ok x)
|
||||
|> Task.map (\_ -> {})
|
||||
Task.ok({})
|
||||
|> Task.await(\_ -> Task.ok(x))
|
||||
|> Task.map(\_ -> {})
|
||||
|
|
|
@ -7,45 +7,45 @@ IO a : Task a []
|
|||
|
||||
main : Task {} []
|
||||
main =
|
||||
{ value, isError } = PlatformTasks.getInt!
|
||||
inputResult =
|
||||
if isError then
|
||||
Err GetIntError
|
||||
{ value, is_error } = PlatformTasks.get_int!
|
||||
input_result =
|
||||
if is_error then
|
||||
Err(GetIntError)
|
||||
else
|
||||
Ok value
|
||||
Ok(value)
|
||||
|
||||
when inputResult is
|
||||
Ok n ->
|
||||
when input_result is
|
||||
Ok(n) ->
|
||||
x : Expr
|
||||
x = Var "x"
|
||||
x = Var("x")
|
||||
|
||||
f : Expr
|
||||
f = pow x x
|
||||
f = pow(x, x)
|
||||
|
||||
nest deriv n f # original koka n = 10
|
||||
|> Task.map \_ -> {}
|
||||
nest(deriv, n, f) # original koka n = 10
|
||||
|> Task.map(\_ -> {})
|
||||
|
||||
Err GetIntError ->
|
||||
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||
Err(GetIntError) ->
|
||||
PlatformTasks.put_line("Error: Failed to get Integer from stdin.")
|
||||
|
||||
nestHelp : I64, (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
||||
nestHelp = \s, f, m, x ->
|
||||
nest_help : I64, (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
||||
nest_help = \s, f, m, x ->
|
||||
when m is
|
||||
0 -> Task.ok x
|
||||
0 -> Task.ok(x)
|
||||
_ ->
|
||||
w = f! (s - m) x
|
||||
nestHelp s f (m - 1) w
|
||||
w = f!((s - m), x)
|
||||
nest_help(s, f, (m - 1), w)
|
||||
|
||||
nest : (I64, Expr -> IO Expr), I64, Expr -> IO Expr
|
||||
nest = \f, n, e -> nestHelp n f n e
|
||||
nest = \f, n, e -> nest_help(n, f, n, e)
|
||||
|
||||
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
|
||||
Pair (Ok div) (Ok mod) -> Ok { div, mod }
|
||||
_ -> Err DivByZero
|
||||
when Pair(Num.div_trunc_checked(l, r), Num.rem_checked(l, r)) is
|
||||
Pair(Ok(div), Ok(mod)) -> Ok({ div, mod })
|
||||
_ -> Err(DivByZero)
|
||||
|
||||
pown : I64, I64 -> I64
|
||||
pown = \a, n ->
|
||||
|
@ -53,119 +53,119 @@ pown = \a, n ->
|
|||
0 -> 1
|
||||
1 -> a
|
||||
_ ->
|
||||
when divmod n 2 is
|
||||
Ok { div, mod } ->
|
||||
b = pown a div
|
||||
when divmod(n, 2) is
|
||||
Ok({ div, mod }) ->
|
||||
b = pown(a, div)
|
||||
|
||||
b * b * (if mod == 0 then 1 else a)
|
||||
|
||||
Err DivByZero ->
|
||||
Err(DivByZero) ->
|
||||
-1
|
||||
|
||||
add : Expr, Expr -> Expr
|
||||
add = \a, b ->
|
||||
when Pair a b is
|
||||
Pair (Val n) (Val m) ->
|
||||
Val (n + m)
|
||||
when Pair(a, b) is
|
||||
Pair(Val(n), Val(m)) ->
|
||||
Val((n + m))
|
||||
|
||||
Pair (Val 0) f ->
|
||||
Pair(Val(0), f) ->
|
||||
f
|
||||
|
||||
Pair f (Val 0) ->
|
||||
Pair(f, Val(0)) ->
|
||||
f
|
||||
|
||||
Pair f (Val n) ->
|
||||
add (Val n) f
|
||||
Pair(f, Val(n)) ->
|
||||
add(Val(n), f)
|
||||
|
||||
Pair (Val n) (Add (Val m) f) ->
|
||||
add (Val (n + m)) f
|
||||
Pair(Val(n), Add(Val(m), f)) ->
|
||||
add(Val((n + m)), f)
|
||||
|
||||
Pair f (Add (Val n) g) ->
|
||||
add (Val n) (add f g)
|
||||
Pair(f, Add(Val(n), g)) ->
|
||||
add(Val(n), add(f, g))
|
||||
|
||||
Pair (Add f g) h ->
|
||||
add f (add g h)
|
||||
Pair(Add(f, g), h) ->
|
||||
add(f, add(g, h))
|
||||
|
||||
Pair f g ->
|
||||
Add f g
|
||||
Pair(f, g) ->
|
||||
Add(f, g)
|
||||
|
||||
mul : Expr, Expr -> Expr
|
||||
mul = \a, b ->
|
||||
when Pair a b is
|
||||
Pair (Val n) (Val m) ->
|
||||
Val (n * m)
|
||||
when Pair(a, b) is
|
||||
Pair(Val(n), Val(m)) ->
|
||||
Val((n * m))
|
||||
|
||||
Pair (Val 0) _ ->
|
||||
Val 0
|
||||
Pair(Val(0), _) ->
|
||||
Val(0)
|
||||
|
||||
Pair _ (Val 0) ->
|
||||
Val 0
|
||||
Pair(_, Val(0)) ->
|
||||
Val(0)
|
||||
|
||||
Pair (Val 1) f ->
|
||||
Pair(Val(1), f) ->
|
||||
f
|
||||
|
||||
Pair f (Val 1) ->
|
||||
Pair(f, Val(1)) ->
|
||||
f
|
||||
|
||||
Pair f (Val n) ->
|
||||
mul (Val n) f
|
||||
Pair(f, Val(n)) ->
|
||||
mul(Val(n), f)
|
||||
|
||||
Pair (Val n) (Mul (Val m) f) ->
|
||||
mul (Val (n * m)) f
|
||||
Pair(Val(n), Mul(Val(m), f)) ->
|
||||
mul(Val((n * m)), f)
|
||||
|
||||
Pair f (Mul (Val n) g) ->
|
||||
mul (Val n) (mul f g)
|
||||
Pair(f, Mul(Val(n), g)) ->
|
||||
mul(Val(n), mul(f, g))
|
||||
|
||||
Pair (Mul f g) h ->
|
||||
mul f (mul g h)
|
||||
Pair(Mul(f, g), h) ->
|
||||
mul(f, mul(g, h))
|
||||
|
||||
Pair f g ->
|
||||
Mul f g
|
||||
Pair(f, g) ->
|
||||
Mul(f, g)
|
||||
|
||||
pow : Expr, Expr -> Expr
|
||||
pow = \a, b ->
|
||||
when Pair a b is
|
||||
Pair (Val m) (Val n) -> Val (pown m n)
|
||||
Pair _ (Val 0) -> Val 1
|
||||
Pair f (Val 1) -> f
|
||||
Pair (Val 0) _ -> Val 0
|
||||
Pair f g -> Pow f g
|
||||
when Pair(a, b) is
|
||||
Pair(Val(m), Val(n)) -> Val(pown(m, n))
|
||||
Pair(_, Val(0)) -> Val(1)
|
||||
Pair(f, Val(1)) -> f
|
||||
Pair(Val(0), _) -> Val(0)
|
||||
Pair(f, g) -> Pow(f, g)
|
||||
|
||||
ln : Expr -> Expr
|
||||
ln = \f ->
|
||||
when f is
|
||||
Val 1 -> Val 0
|
||||
_ -> Ln f
|
||||
Val(1) -> Val(0)
|
||||
_ -> Ln(f)
|
||||
|
||||
d : Str, Expr -> Expr
|
||||
d = \x, expr ->
|
||||
when expr is
|
||||
Val _ -> Val 0
|
||||
Var y -> if x == y then Val 1 else Val 0
|
||||
Add f g -> add (d x f) (d x g)
|
||||
Mul f g -> add (mul f (d x g)) (mul g (d x f))
|
||||
Pow f g ->
|
||||
mul (pow f g) (add (mul (mul g (d x f)) (pow f (Val (-1)))) (mul (ln f) (d x g)))
|
||||
Val(_) -> Val(0)
|
||||
Var(y) -> if x == y then Val(1) else Val(0)
|
||||
Add(f, g) -> add(d(x, f), d(x, g))
|
||||
Mul(f, g) -> add(mul(f, d(x, g)), mul(g, d(x, f)))
|
||||
Pow(f, g) ->
|
||||
mul(pow(f, g), add(mul(mul(g, d(x, f)), pow(f, Val(-1))), mul(ln(f), d(x, g))))
|
||||
|
||||
Ln f ->
|
||||
mul (d x f) (pow f (Val (-1)))
|
||||
Ln(f) ->
|
||||
mul(d(x, f), pow(f, Val(-1)))
|
||||
|
||||
count : Expr -> I64
|
||||
count = \expr ->
|
||||
when expr is
|
||||
Val _ -> 1
|
||||
Var _ -> 1
|
||||
Add f g -> count f + count g
|
||||
Mul f g -> count f + count g
|
||||
Pow f g -> count f + count g
|
||||
Ln f -> count f
|
||||
Val(_) -> 1
|
||||
Var(_) -> 1
|
||||
Add(f, g) -> count(f) + count(g)
|
||||
Mul(f, g) -> count(f) + count(g)
|
||||
Pow(f, g) -> count(f) + count(g)
|
||||
Ln(f) -> count(f)
|
||||
|
||||
deriv : I64, Expr -> IO Expr
|
||||
deriv = \i, f ->
|
||||
fprime = d "x" f
|
||||
fprime = d("x", f)
|
||||
line =
|
||||
Num.toStr (i + 1)
|
||||
|> Str.concat " count: "
|
||||
|> Str.concat (Num.toStr (count fprime))
|
||||
PlatformTasks.putLine! line
|
||||
Task.ok fprime
|
||||
Num.to_str((i + 1))
|
||||
|> Str.concat(" count: ")
|
||||
|> Str.concat(Num.to_str(count(fprime)))
|
||||
PlatformTasks.put_line!(line)
|
||||
Task.ok(fprime)
|
||||
|
|
|
@ -8,6 +8,6 @@ main =
|
|||
if Bool.true then
|
||||
Issue2279Help.text
|
||||
else
|
||||
Issue2279Help.asText 42
|
||||
Issue2279Help.as_text(42)
|
||||
|
||||
PlatformTasks.putLine text
|
||||
PlatformTasks.put_line(text)
|
||||
|
|
|
@ -4,63 +4,63 @@ import pf.PlatformTasks
|
|||
|
||||
main : Task {} []
|
||||
main =
|
||||
{ value, isError } = PlatformTasks.getInt!
|
||||
inputResult =
|
||||
if isError then
|
||||
Err GetIntError
|
||||
{ value, is_error } = PlatformTasks.get_int!
|
||||
input_result =
|
||||
if is_error then
|
||||
Err(GetIntError)
|
||||
else
|
||||
Ok value
|
||||
Ok(value)
|
||||
|
||||
when inputResult is
|
||||
Ok n ->
|
||||
queens n # original koka 13
|
||||
|> Num.toStr
|
||||
|> PlatformTasks.putLine
|
||||
when input_result is
|
||||
Ok(n) ->
|
||||
queens(n) # original koka 13
|
||||
|> Num.to_str
|
||||
|> PlatformTasks.put_line
|
||||
|
||||
Err GetIntError ->
|
||||
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||
Err(GetIntError) ->
|
||||
PlatformTasks.put_line("Error: Failed to get Integer from stdin.")
|
||||
|
||||
ConsList a : [Nil, Cons a (ConsList a)]
|
||||
|
||||
queens = \n -> length (findSolutions n n)
|
||||
queens = \n -> length(find_solutions(n, n))
|
||||
|
||||
findSolutions = \n, k ->
|
||||
find_solutions = \n, k ->
|
||||
if k <= 0 then
|
||||
# should we use U64 as input type here instead?
|
||||
Cons Nil Nil
|
||||
Cons(Nil, Nil)
|
||||
else
|
||||
extend n Nil (findSolutions n (k - 1))
|
||||
extend(n, Nil, find_solutions(n, (k - 1)))
|
||||
|
||||
extend = \n, acc, solutions ->
|
||||
when solutions is
|
||||
Nil -> acc
|
||||
Cons soln rest -> extend n (appendSafe n soln acc) rest
|
||||
Cons(soln, rest) -> extend(n, append_safe(n, soln, acc), rest)
|
||||
|
||||
appendSafe : I64, ConsList I64, ConsList (ConsList I64) -> ConsList (ConsList I64)
|
||||
appendSafe = \k, soln, solns ->
|
||||
append_safe : I64, ConsList I64, ConsList (ConsList I64) -> ConsList (ConsList I64)
|
||||
append_safe = \k, soln, solns ->
|
||||
if k <= 0 then
|
||||
solns
|
||||
else if safe k 1 soln then
|
||||
appendSafe (k - 1) soln (Cons (Cons k soln) solns)
|
||||
else if safe(k, 1, soln) then
|
||||
append_safe((k - 1), soln, Cons(Cons(k, soln), solns))
|
||||
else
|
||||
appendSafe (k - 1) soln solns
|
||||
append_safe((k - 1), soln, solns)
|
||||
|
||||
safe : I64, I64, ConsList I64 -> Bool
|
||||
safe = \queen, diagonal, xs ->
|
||||
when xs is
|
||||
Nil -> Bool.true
|
||||
Cons q t ->
|
||||
Cons(q, t) ->
|
||||
if queen != q && queen != q + diagonal && queen != q - diagonal then
|
||||
safe queen (diagonal + 1) t
|
||||
safe(queen, (diagonal + 1), t)
|
||||
else
|
||||
Bool.false
|
||||
|
||||
length : ConsList a -> I64
|
||||
length = \xs ->
|
||||
lengthHelp xs 0
|
||||
length_help(xs, 0)
|
||||
|
||||
lengthHelp : ConsList a, I64 -> I64
|
||||
lengthHelp = \foobar, acc ->
|
||||
length_help : ConsList a, I64 -> I64
|
||||
length_help = \foobar, acc ->
|
||||
when foobar is
|
||||
Cons _ lrest -> lengthHelp lrest (1 + acc)
|
||||
Cons(_, lrest) -> length_help(lrest, (1 + acc))
|
||||
Nil -> acc
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
hosted PlatformTasks
|
||||
exposes [putLine, putInt, getInt]
|
||||
exposes [put_line, put_int, get_int]
|
||||
imports []
|
||||
|
||||
putLine : Str -> Task {} *
|
||||
put_line : Str -> Task {} *
|
||||
|
||||
putInt : I64 -> Task {} *
|
||||
put_int : I64 -> Task {} *
|
||||
|
||||
getInt : Task { value : I64, isError : Bool } *
|
||||
get_int : Task { value : I64, is_error : Bool } *
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
app [main] { pf: platform "main.roc" }
|
||||
|
||||
main = Task.ok {}
|
||||
main = Task.ok({})
|
||||
|
|
|
@ -10,11 +10,11 @@ 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__mainForHost_0_caller(*const u8, [*]u8, [*]u8) void;
|
||||
extern fn roc__mainForHost_0_size() i64;
|
||||
extern fn roc__mainForHost_0_result_size() i64;
|
||||
extern fn roc__main_for_host_1_exposed_generic([*]u8) void;
|
||||
extern fn roc__main_for_host_1_exposed_size() i64;
|
||||
extern fn roc__main_for_host_0_caller(*const u8, [*]u8, [*]u8) void;
|
||||
extern fn roc__main_for_host_0_size() i64;
|
||||
extern fn roc__main_for_host_0_result_size() i64;
|
||||
|
||||
const Align = 2 * @alignOf(usize);
|
||||
extern fn malloc(size: usize) callconv(.C) ?*align(Align) anyopaque;
|
||||
|
@ -113,7 +113,7 @@ const Unit = extern struct {};
|
|||
|
||||
pub export fn main() u8 {
|
||||
// The size might be zero; if so, make it at least 8 so that we don't have a nullptr
|
||||
const size = @max(@as(usize, @intCast(roc__mainForHost_1_exposed_size())), 8);
|
||||
const size = @max(@as(usize, @intCast(roc__main_for_host_1_exposed_size())), 8);
|
||||
const raw_output = roc_alloc(@as(usize, @intCast(size)), @alignOf(u64)) orelse {
|
||||
std.log.err("Memory allocation failed", .{});
|
||||
return 1;
|
||||
|
@ -124,7 +124,7 @@ pub export fn main() u8 {
|
|||
roc_dealloc(raw_output, @alignOf(u64));
|
||||
}
|
||||
|
||||
roc__mainForHost_1_exposed_generic(output);
|
||||
roc__main_for_host_1_exposed_generic(output);
|
||||
|
||||
const closure_data_pointer = @as([*]u8, @ptrCast(output));
|
||||
|
||||
|
@ -137,7 +137,7 @@ fn call_the_closure(closure_data_pointer: [*]u8) void {
|
|||
const allocator = std.heap.page_allocator;
|
||||
|
||||
// The size might be zero; if so, make it at least 8 so that we don't have a nullptr
|
||||
const size = @max(roc__mainForHost_0_result_size(), 8);
|
||||
const size = @max(roc__main_for_host_0_result_size(), 8);
|
||||
const raw_output = allocator.alignedAlloc(u8, @alignOf(u64), @as(usize, @intCast(size))) catch unreachable;
|
||||
const output = @as([*]u8, @ptrCast(raw_output));
|
||||
|
||||
|
@ -147,13 +147,13 @@ fn call_the_closure(closure_data_pointer: [*]u8) void {
|
|||
|
||||
const flags: u8 = 0;
|
||||
|
||||
roc__mainForHost_0_caller(&flags, closure_data_pointer, output);
|
||||
roc__main_for_host_0_caller(&flags, closure_data_pointer, output);
|
||||
|
||||
// The closure returns result, nothing interesting to do with it
|
||||
return;
|
||||
}
|
||||
|
||||
pub export fn roc_fx_putInt(int: i64) i64 {
|
||||
pub export fn roc_fx_put_int(int: i64) i64 {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
stdout.print("{d}", .{int}) catch unreachable;
|
||||
|
@ -163,7 +163,7 @@ pub export fn roc_fx_putInt(int: i64) i64 {
|
|||
return 0;
|
||||
}
|
||||
|
||||
export fn roc_fx_putLine(rocPath: *str.RocStr) callconv(.C) void {
|
||||
export fn roc_fx_put_line(rocPath: *str.RocStr) callconv(.C) void {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
for (rocPath.asSlice()) |char| {
|
||||
|
@ -180,14 +180,14 @@ const GetInt = extern struct {
|
|||
|
||||
comptime {
|
||||
if (@sizeOf(usize) == 8) {
|
||||
@export(roc_fx_getInt_64bit, .{ .name = "roc_fx_getInt" });
|
||||
@export(roc_fx_get_int_64bit, .{ .name = "roc_fx_get_int" });
|
||||
} else {
|
||||
@export(roc_fx_getInt_32bit, .{ .name = "roc_fx_getInt" });
|
||||
@export(roc_fx_get_int_32bit, .{ .name = "roc_fx_get_int" });
|
||||
}
|
||||
}
|
||||
|
||||
fn roc_fx_getInt_64bit() callconv(.C) GetInt {
|
||||
if (roc_fx_getInt_help()) |value| {
|
||||
fn roc_fx_get_int_64bit() callconv(.C) GetInt {
|
||||
if (roc_fx_get_int_help()) |value| {
|
||||
const get_int = GetInt{ .is_error = false, .value = value };
|
||||
return get_int;
|
||||
} else |err| switch (err) {
|
||||
|
@ -202,8 +202,8 @@ fn roc_fx_getInt_64bit() callconv(.C) GetInt {
|
|||
return 0;
|
||||
}
|
||||
|
||||
fn roc_fx_getInt_32bit(output: *GetInt) callconv(.C) void {
|
||||
if (roc_fx_getInt_help()) |value| {
|
||||
fn roc_fx_get_int_32bit(output: *GetInt) callconv(.C) void {
|
||||
if (roc_fx_get_int_help()) |value| {
|
||||
const get_int = GetInt{ .is_error = false, .value = value };
|
||||
output.* = get_int;
|
||||
} else |err| switch (err) {
|
||||
|
@ -218,7 +218,7 @@ fn roc_fx_getInt_32bit(output: *GetInt) callconv(.C) void {
|
|||
return;
|
||||
}
|
||||
|
||||
fn roc_fx_getInt_help() !i64 {
|
||||
fn roc_fx_get_int_help() !i64 {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
stdout.print("Please enter an integer\n", .{}) catch unreachable;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ platform "benchmarks"
|
|||
exposes []
|
||||
packages {}
|
||||
imports []
|
||||
provides [mainForHost]
|
||||
provides [main_for_host]
|
||||
|
||||
mainForHost : Task {} []
|
||||
mainForHost = main
|
||||
main_for_host : Task {} []
|
||||
main_for_host = main
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -10,75 +10,75 @@ Map : Tree I64 Bool
|
|||
|
||||
ConsList a : [Nil, Cons a (ConsList a)]
|
||||
|
||||
makeMap : I64, I64 -> ConsList Map
|
||||
makeMap = \freq, n ->
|
||||
makeMapHelp freq n Leaf Nil
|
||||
make_map : I64, I64 -> ConsList Map
|
||||
make_map = \freq, n ->
|
||||
make_map_help(freq, n, Leaf, Nil)
|
||||
|
||||
makeMapHelp : I64, I64, Map, ConsList Map -> ConsList Map
|
||||
makeMapHelp = \freq, n, m, acc ->
|
||||
make_map_help : I64, I64, Map, ConsList Map -> ConsList Map
|
||||
make_map_help = \freq, n, m, acc ->
|
||||
when n is
|
||||
0 -> Cons m acc
|
||||
0 -> Cons(m, acc)
|
||||
_ ->
|
||||
powerOf10 =
|
||||
power_of10 =
|
||||
n % 10 == 0
|
||||
|
||||
m1 = insert m n powerOf10
|
||||
m1 = insert(m, n, power_of10)
|
||||
|
||||
isFrequency =
|
||||
is_frequency =
|
||||
n % freq == 0
|
||||
|
||||
x = (if isFrequency then Cons m1 acc else acc)
|
||||
x = (if is_frequency then Cons(m1, acc) else acc)
|
||||
|
||||
makeMapHelp freq (n - 1) m1 x
|
||||
make_map_help(freq, (n - 1), m1, x)
|
||||
|
||||
fold : (a, b, omega -> omega), Tree a b, omega -> omega
|
||||
fold = \f, tree, b ->
|
||||
when tree is
|
||||
Leaf -> b
|
||||
Node _ l k v r -> fold f r (f k v (fold f l b))
|
||||
Node(_, l, k, v, r) -> fold(f, r, f(k, v, fold(f, l, b)))
|
||||
|
||||
main : Task {} []
|
||||
main =
|
||||
{ value, isError } = PlatformTasks.getInt!
|
||||
inputResult =
|
||||
if isError then
|
||||
Err GetIntError
|
||||
{ value, is_error } = PlatformTasks.get_int!
|
||||
input_result =
|
||||
if is_error then
|
||||
Err(GetIntError)
|
||||
else
|
||||
Ok value
|
||||
Ok(value)
|
||||
|
||||
when inputResult is
|
||||
Ok n ->
|
||||
when input_result is
|
||||
Ok(n) ->
|
||||
# original koka n = 4_200_000
|
||||
ms : ConsList Map
|
||||
ms = makeMap 5 n
|
||||
ms = make_map(5, n)
|
||||
|
||||
when ms is
|
||||
Cons head _ ->
|
||||
val = fold (\_, v, r -> if v then r + 1 else r) head 0
|
||||
Cons(head, _) ->
|
||||
val = fold(\_, v, r -> if v then r + 1 else r, head, 0)
|
||||
|
||||
val
|
||||
|> Num.toStr
|
||||
|> PlatformTasks.putLine
|
||||
|> Num.to_str
|
||||
|> PlatformTasks.put_line
|
||||
|
||||
Nil ->
|
||||
PlatformTasks.putLine "fail"
|
||||
PlatformTasks.put_line("fail")
|
||||
|
||||
Err GetIntError ->
|
||||
PlatformTasks.putLine "Error: Failed to get Integer from stdin."
|
||||
Err(GetIntError) ->
|
||||
PlatformTasks.put_line("Error: Failed to get Integer from stdin.")
|
||||
|
||||
insert : Tree (Num k) v, Num k, v -> Tree (Num k) v
|
||||
insert = \t, k, v -> if isRed t then setBlack (ins t k v) else ins t k v
|
||||
insert = \t, k, v -> if is_red(t) then set_black(ins(t, k, v)) else ins(t, k, v)
|
||||
|
||||
setBlack : Tree a b -> Tree a b
|
||||
setBlack = \tree ->
|
||||
set_black : Tree a b -> Tree a b
|
||||
set_black = \tree ->
|
||||
when tree is
|
||||
Node _ l k v r -> Node Black l k v r
|
||||
Node(_, l, k, v, r) -> Node(Black, l, k, v, r)
|
||||
_ -> tree
|
||||
|
||||
isRed : Tree a b -> Bool
|
||||
isRed = \tree ->
|
||||
is_red : Tree a b -> Bool
|
||||
is_red = \tree ->
|
||||
when tree is
|
||||
Node Red _ _ _ _ -> Bool.true
|
||||
Node(Red, _, _, _, _) -> Bool.true
|
||||
_ -> Bool.false
|
||||
|
||||
lt = \x, y -> x < y
|
||||
|
@ -86,43 +86,43 @@ lt = \x, y -> x < y
|
|||
ins : Tree (Num k) v, Num k, v -> Tree (Num k) v
|
||||
ins = \tree, kx, vx ->
|
||||
when tree is
|
||||
Leaf -> Node Red Leaf kx vx Leaf
|
||||
Node Red a ky vy b ->
|
||||
if lt kx ky then
|
||||
Node Red (ins a kx vx) ky vy b
|
||||
else if lt ky kx then
|
||||
Node Red a ky vy (ins b kx vx)
|
||||
Leaf -> Node(Red, Leaf, kx, vx, Leaf)
|
||||
Node(Red, a, ky, vy, b) ->
|
||||
if lt(kx, ky) then
|
||||
Node(Red, ins(a, kx, vx), ky, vy, b)
|
||||
else if lt(ky, kx) then
|
||||
Node(Red, a, ky, vy, ins(b, kx, vx))
|
||||
else
|
||||
Node Red a ky vy (ins b kx vx)
|
||||
Node(Red, a, ky, vy, ins(b, kx, vx))
|
||||
|
||||
Node Black a ky vy b ->
|
||||
if lt kx ky then
|
||||
if isRed a then
|
||||
balance1 (Node Black Leaf ky vy b) (ins a kx vx)
|
||||
Node(Black, a, ky, vy, b) ->
|
||||
if lt(kx, ky) then
|
||||
if is_red(a) then
|
||||
balance1(Node(Black, Leaf, ky, vy, b), ins(a, kx, vx))
|
||||
else
|
||||
Node Black (ins a kx vx) ky vy b
|
||||
else if lt ky kx then
|
||||
if isRed b then
|
||||
balance2 (Node Black a ky vy Leaf) (ins b kx vx)
|
||||
Node(Black, ins(a, kx, vx), ky, vy, b)
|
||||
else if lt(ky, kx) then
|
||||
if is_red(b) then
|
||||
balance2(Node(Black, a, ky, vy, Leaf), ins(b, kx, vx))
|
||||
else
|
||||
Node Black a ky vy (ins b kx vx)
|
||||
Node(Black, a, ky, vy, ins(b, kx, vx))
|
||||
else
|
||||
Node Black a kx vx b
|
||||
Node(Black, a, kx, vx, b)
|
||||
|
||||
balance1 : Tree a b, Tree a b -> Tree a b
|
||||
balance1 = \tree1, tree2 ->
|
||||
when tree1 is
|
||||
Leaf -> Leaf
|
||||
Node _ _ kv vv t ->
|
||||
Node(_, _, kv, vv, t) ->
|
||||
when tree2 is
|
||||
Node _ (Node Red l kx vx r1) ky vy r2 ->
|
||||
Node Red (Node Black l kx vx r1) ky vy (Node Black r2 kv vv t)
|
||||
Node(_, Node(Red, l, kx, vx, r1), ky, vy, r2) ->
|
||||
Node(Red, Node(Black, l, kx, vx, r1), ky, vy, Node(Black, r2, kv, vv, t))
|
||||
|
||||
Node _ l1 ky vy (Node Red l2 kx vx r) ->
|
||||
Node Red (Node Black l1 ky vy l2) kx vx (Node Black r kv vv t)
|
||||
Node(_, l1, ky, vy, Node(Red, l2, kx, vx, r)) ->
|
||||
Node(Red, Node(Black, l1, ky, vy, l2), kx, vx, Node(Black, r, kv, vv, t))
|
||||
|
||||
Node _ l ky vy r ->
|
||||
Node Black (Node Red l ky vy r) kv vv t
|
||||
Node(_, l, ky, vy, r) ->
|
||||
Node(Black, Node(Red, l, ky, vy, r), kv, vv, t)
|
||||
|
||||
Leaf -> Leaf
|
||||
|
||||
|
@ -130,16 +130,16 @@ balance2 : Tree a b, Tree a b -> Tree a b
|
|||
balance2 = \tree1, tree2 ->
|
||||
when tree1 is
|
||||
Leaf -> Leaf
|
||||
Node _ t kv vv _ ->
|
||||
Node(_, t, kv, vv, _) ->
|
||||
when tree2 is
|
||||
Node _ (Node Red l kx1 vx1 r1) ky vy r2 ->
|
||||
Node Red (Node Black t kv vv l) kx1 vx1 (Node Black r1 ky vy r2)
|
||||
Node(_, Node(Red, l, kx1, vx1, r1), ky, vy, r2) ->
|
||||
Node(Red, Node(Black, t, kv, vv, l), kx1, vx1, Node(Black, r1, ky, vy, r2))
|
||||
|
||||
Node _ l1 ky vy (Node Red l2 kx2 vx2 r2) ->
|
||||
Node Red (Node Black t kv vv l1) ky vy (Node Black l2 kx2 vx2 r2)
|
||||
Node(_, l1, ky, vy, Node(Red, l2, kx2, vx2, r2)) ->
|
||||
Node(Red, Node(Black, t, kv, vv, l1), ky, vy, Node(Black, l2, kx2, vx2, r2))
|
||||
|
||||
Node _ l ky vy r ->
|
||||
Node Black t kv vv (Node Red l ky vy r)
|
||||
Node(_, l, ky, vy, r) ->
|
||||
Node(Black, t, kv, vv, Node(Red, l, ky, vy, r))
|
||||
|
||||
Leaf ->
|
||||
Leaf
|
||||
|
|
|
@ -5,41 +5,41 @@ import pf.PlatformTasks
|
|||
main : Task {} []
|
||||
main =
|
||||
tree : RedBlackTree I64 {}
|
||||
tree = insert 0 {} Empty
|
||||
tree = insert(0, {}, Empty)
|
||||
|
||||
tree
|
||||
|> show
|
||||
|> PlatformTasks.putLine
|
||||
|> PlatformTasks.put_line
|
||||
|
||||
show : RedBlackTree I64 {} -> Str
|
||||
show = \tree -> showRBTree tree Num.toStr (\{} -> "{}")
|
||||
show = \tree -> show_rb_tree(tree, Num.to_str, \{} -> "{}")
|
||||
|
||||
showRBTree : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
|
||||
showRBTree = \tree, showKey, showValue ->
|
||||
show_rb_tree : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
|
||||
show_rb_tree = \tree, show_key, show_value ->
|
||||
when tree is
|
||||
Empty -> "Empty"
|
||||
Node color key value left right ->
|
||||
sColor = showColor color
|
||||
sKey = showKey key
|
||||
sValue = showValue value
|
||||
sL = nodeInParens left showKey showValue
|
||||
sR = nodeInParens right showKey showValue
|
||||
Node(color, key, value, left, right) ->
|
||||
s_color = show_color(color)
|
||||
s_key = show_key(key)
|
||||
s_value = show_value(value)
|
||||
s_l = node_in_parens(left, show_key, show_value)
|
||||
s_r = node_in_parens(right, show_key, show_value)
|
||||
|
||||
"Node $(sColor) $(sKey) $(sValue) $(sL) $(sR)"
|
||||
"Node $(s_color) $(s_key) $(s_value) $(s_l) $(s_r)"
|
||||
|
||||
nodeInParens : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
|
||||
nodeInParens = \tree, showKey, showValue ->
|
||||
node_in_parens : RedBlackTree k v, (k -> Str), (v -> Str) -> Str
|
||||
node_in_parens = \tree, show_key, show_value ->
|
||||
when tree is
|
||||
Empty ->
|
||||
showRBTree tree showKey showValue
|
||||
show_rb_tree(tree, show_key, show_value)
|
||||
|
||||
Node _ _ _ _ _ ->
|
||||
inner = showRBTree tree showKey showValue
|
||||
Node(_, _, _, _, _) ->
|
||||
inner = show_rb_tree(tree, show_key, show_value)
|
||||
|
||||
"($(inner))"
|
||||
|
||||
showColor : NodeColor -> Str
|
||||
showColor = \color ->
|
||||
show_color : NodeColor -> Str
|
||||
show_color = \color ->
|
||||
when color is
|
||||
Red -> "Red"
|
||||
Black -> "Black"
|
||||
|
@ -52,49 +52,51 @@ Key k : Num k
|
|||
|
||||
insert : Key k, v, RedBlackTree (Key k) v -> RedBlackTree (Key k) v
|
||||
insert = \key, value, dict ->
|
||||
when insertHelp key value dict is
|
||||
Node Red k v l r -> Node Black k v l r
|
||||
when insert_help(key, value, dict) is
|
||||
Node(Red, k, v, l, r) -> Node(Black, k, v, l, r)
|
||||
x -> x
|
||||
|
||||
insertHelp : Key k, v, RedBlackTree (Key k) v -> RedBlackTree (Key k) v
|
||||
insertHelp = \key, value, dict ->
|
||||
insert_help : Key k, v, RedBlackTree (Key k) v -> RedBlackTree (Key k) v
|
||||
insert_help = \key, value, dict ->
|
||||
when dict is
|
||||
Empty ->
|
||||
# New nodes are always red. If it violates the rules, it will be fixed
|
||||
# when balancing.
|
||||
Node Red key value Empty Empty
|
||||
Node(Red, key, value, Empty, Empty)
|
||||
|
||||
Node nColor nKey nValue nLeft nRight ->
|
||||
when Num.compare key nKey is
|
||||
LT -> balance nColor nKey nValue (insertHelp key value nLeft) nRight
|
||||
EQ -> Node nColor nKey value nLeft nRight
|
||||
GT -> balance nColor nKey nValue nLeft (insertHelp key value nRight)
|
||||
Node(n_color, n_key, n_value, n_left, n_right) ->
|
||||
when Num.compare(key, n_key) is
|
||||
LT -> balance(n_color, n_key, n_value, insert_help(key, value, n_left), n_right)
|
||||
EQ -> Node(n_color, n_key, value, n_left, n_right)
|
||||
GT -> balance(n_color, n_key, n_value, n_left, insert_help(key, value, n_right))
|
||||
|
||||
balance : NodeColor, k, v, RedBlackTree k v, RedBlackTree k v -> RedBlackTree k v
|
||||
balance = \color, key, value, left, right ->
|
||||
when right is
|
||||
Node Red rK rV rLeft rRight ->
|
||||
Node(Red, r_k, r_v, r_left, r_right) ->
|
||||
when left is
|
||||
Node Red lK lV lLeft lRight ->
|
||||
Node
|
||||
Red
|
||||
key
|
||||
value
|
||||
(Node Black lK lV lLeft lRight)
|
||||
(Node Black rK rV rLeft rRight)
|
||||
Node(Red, l_k, l_v, l_left, l_right) ->
|
||||
Node(
|
||||
Red,
|
||||
key,
|
||||
value,
|
||||
Node(Black, l_k, l_v, l_left, l_right),
|
||||
Node(Black, r_k, r_v, r_left, r_right),
|
||||
)
|
||||
|
||||
_ ->
|
||||
Node color rK rV (Node Red key value left rLeft) rRight
|
||||
Node(color, r_k, r_v, Node(Red, key, value, left, r_left), r_right)
|
||||
|
||||
_ ->
|
||||
when left is
|
||||
Node Red lK lV (Node Red llK llV llLeft llRight) lRight ->
|
||||
Node
|
||||
Red
|
||||
lK
|
||||
lV
|
||||
(Node Black llK llV llLeft llRight)
|
||||
(Node Black key value lRight right)
|
||||
Node(Red, l_k, l_v, Node(Red, ll_k, ll_v, ll_left, ll_right), l_right) ->
|
||||
Node(
|
||||
Red,
|
||||
l_k,
|
||||
l_v,
|
||||
Node(Black, ll_k, ll_v, ll_left, ll_right),
|
||||
Node(Black, key, value, l_right, right),
|
||||
)
|
||||
|
||||
_ ->
|
||||
Node color key value left right
|
||||
Node(color, key, value, left, right)
|
||||
|
|
|
@ -4,10 +4,10 @@ import pf.PlatformTasks
|
|||
import AStar
|
||||
|
||||
main =
|
||||
PlatformTasks.putLine! (showBool test1)
|
||||
PlatformTasks.put_line!(show_bool(test1))
|
||||
|
||||
showBool : Bool -> Str
|
||||
showBool = \b ->
|
||||
show_bool : Bool -> Str
|
||||
show_bool = \b ->
|
||||
if
|
||||
b
|
||||
then
|
||||
|
@ -24,14 +24,14 @@ 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
|
||||
|
||||
when AStar.findPath cost step 1 4 is
|
||||
Ok path -> path
|
||||
Err _ -> []
|
||||
when AStar.find_path(cost, step, 1, 4) is
|
||||
Ok(path) -> path
|
||||
Err(_) -> []
|
||||
|
|
|
@ -7,11 +7,11 @@ IO a : Task a []
|
|||
|
||||
main : IO {}
|
||||
main =
|
||||
when Base64.fromBytes (Str.toUtf8 "Hello World") is
|
||||
Err _ -> PlatformTasks.putLine "sadness"
|
||||
Ok encoded ->
|
||||
PlatformTasks.putLine! (Str.concat "encoded: " encoded)
|
||||
when Base64.from_bytes(Str.to_utf8("Hello World")) is
|
||||
Err(_) -> PlatformTasks.put_line("sadness")
|
||||
Ok(encoded) ->
|
||||
PlatformTasks.put_line!(Str.concat("encoded: ", encoded))
|
||||
|
||||
when Base64.toStr encoded is
|
||||
Ok decoded -> PlatformTasks.putLine (Str.concat "decoded: " decoded)
|
||||
Err _ -> PlatformTasks.putLine "sadness"
|
||||
when Base64.to_str(encoded) is
|
||||
Ok(decoded) -> PlatformTasks.put_line(Str.concat("decoded: ", decoded))
|
||||
Err(_) -> PlatformTasks.put_line("sadness")
|
||||
|
|
|
@ -213,7 +213,8 @@ mod cli_tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(windows, ignore)]
|
||||
// #[cfg_attr(windows, ignore)]
|
||||
#[ignore]
|
||||
fn false_interpreter() {
|
||||
let cli_build = ExecCli::new(
|
||||
CMD_BUILD,
|
||||
|
@ -877,7 +878,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,
|
||||
|
@ -988,7 +989,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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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!({})
|
||||
|
|
|
@ -4,4 +4,4 @@ import pf.Effect
|
|||
|
||||
main! : {} => {}
|
||||
main! = \{} ->
|
||||
Effect.putLine! "I'm an effect 👻"
|
||||
Effect.put_line!("I'm an effect 👻")
|
||||
|
|
|
@ -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! 😎")
|
||||
|
|
|
@ -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!
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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!({}))")
|
||||
|
|
|
@ -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)")
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -4,4 +4,4 @@ module [
|
|||
|
||||
add = \num1, num2 -> (num1 + num2)
|
||||
|
||||
expect add 1 2 == 3
|
||||
expect add(1, 2) == 3
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -4,8 +4,8 @@ import pf.Host
|
|||
|
||||
line! : {} => Str
|
||||
line! = \{} ->
|
||||
Host.getLine! {}
|
||||
Host.get_line!({})
|
||||
|
||||
char! : {} => U8
|
||||
char! = \{} ->
|
||||
Host.getChar! {}
|
||||
Host.get_char!({})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
app [main] { pf: "platform/main.roc" }
|
||||
|
||||
main : Str
|
||||
main = Dep1.value1 {}
|
||||
main = Dep1.value1({})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
app [main] { pf: "platform/main.roc" }
|
||||
|
||||
main : Str
|
||||
main = Dep1.value1 {}
|
||||
main = Dep1.value1({})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
app [main] { pf: "platform/main.roc" }
|
||||
app [main] { pf: "platform/main.roc" }
|
||||
|
||||
main : Str
|
||||
main = Dep1.value1 {}
|
||||
main = Dep1.value1({})
|
||||
|
|
|
@ -3,4 +3,4 @@ module [value1]
|
|||
import Dep2
|
||||
|
||||
value1 : {} -> Str
|
||||
value1 = \_ -> Dep2.value2 {}
|
||||
value1 = \_ -> Dep2.value2({})
|
||||
|
|
|
@ -3,4 +3,4 @@ app [main] { pf: platform "../../test-platform-simple-zig/main.roc" }
|
|||
import Dep1
|
||||
|
||||
main : Str
|
||||
main = Dep1.value1 {}
|
||||
main = Dep1.value1({})
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -5,4 +5,4 @@ app [main] {
|
|||
import Module
|
||||
|
||||
main =
|
||||
Module.valueFromPkg
|
||||
Module.value_from_pkg
|
||||
|
|
|
@ -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))"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
module { echo } -> [menu]
|
||||
|
||||
menu = \name ->
|
||||
indirect name
|
||||
indirect(name)
|
||||
|
||||
indirect = \name ->
|
||||
echo "Hi, $(name)!"
|
||||
echo("Hi, $(name)!")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
module { sendHttpReq, getEnvVar } -> [hi]
|
||||
module { send_http_req, get_env_var } -> [hi]
|
||||
|
||||
hi : Str
|
||||
hi =
|
||||
|
|
|
@ -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))
|
||||
"""
|
||||
|
|
|
@ -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))
|
||||
"""
|
||||
|
|
|
@ -2,7 +2,7 @@ app [main] {
|
|||
pf: platform "../test-platform-simple-zig/main.roc",
|
||||
}
|
||||
|
||||
import BadAnn { appId: "one" }
|
||||
import BadAnn { app_id: "one" }
|
||||
|
||||
main =
|
||||
""
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module { stdout! } -> [log!]
|
||||
|
||||
log! = \msg, level -> stdout! "$(level):$(msg)"
|
||||
log! = \msg, level -> stdout!("$(level):$(msg)")
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,6 +5,6 @@ import pf.Effect
|
|||
# just a stubbed app for building the test platform
|
||||
main! = \{} ->
|
||||
|
||||
Effect.putLine! ""
|
||||
Effect.put_line!("")
|
||||
|
||||
{}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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!({})
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, "!"),
|
||||
}
|
||||
|
|
|
@ -12,18 +12,18 @@ const Allocator = mem.Allocator;
|
|||
|
||||
const Program = extern struct { init: RocStr, update: Unit, view: Unit };
|
||||
|
||||
extern fn roc__mainForHost_1_exposed() Program;
|
||||
extern fn roc__mainForHost_size() i64;
|
||||
extern fn roc__main_for_host_1_exposed() Program;
|
||||
extern fn roc__main_for_host_size() i64;
|
||||
|
||||
const ConstModel = [*]const u8;
|
||||
const MutModel = [*]u8;
|
||||
|
||||
extern fn roc__mainForHost_0_caller([*]u8, [*]u8, MutModel) void;
|
||||
extern fn roc__mainForHost_0_size() i64;
|
||||
extern fn roc__mainForHost_0_result_size() i64;
|
||||
extern fn roc__main_for_host_0_caller([*]u8, [*]u8, MutModel) void;
|
||||
extern fn roc__main_for_host_0_size() i64;
|
||||
extern fn roc__main_for_host_0_result_size() i64;
|
||||
|
||||
fn allocate_model(allocator: *Allocator) MutModel {
|
||||
const size = roc__mainForHost_0_result_size();
|
||||
const size = roc__main_for_host_0_result_size();
|
||||
const raw_output = allocator.alignedAlloc(u8, @alignOf(u64), @as(usize, @intCast(size))) catch unreachable;
|
||||
const output = @as([*]u8, @ptrCast(raw_output));
|
||||
|
||||
|
@ -34,33 +34,33 @@ fn init(allocator: *Allocator) ConstModel {
|
|||
const closure: [*]u8 = undefined;
|
||||
const output = allocate_model(allocator);
|
||||
|
||||
roc__mainForHost_0_caller(closure, closure, output);
|
||||
roc__main_for_host_0_caller(closure, closure, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
extern fn roc__mainForHost_1_caller(ConstModel, *const RocStr, [*]u8, MutModel) void;
|
||||
extern fn roc__mainForHost_1_size() i64;
|
||||
extern fn roc__mainForHost_1_result_size() i64;
|
||||
extern fn roc__main_for_host_1_caller(ConstModel, *const RocStr, [*]u8, MutModel) void;
|
||||
extern fn roc__main_for_host_1_size() i64;
|
||||
extern fn roc__main_for_host_1_result_size() i64;
|
||||
|
||||
fn update(allocator: *Allocator, model: ConstModel, msg: RocStr) ConstModel {
|
||||
const closure: [*]u8 = undefined;
|
||||
const output = allocate_model(allocator);
|
||||
|
||||
roc__mainForHost_1_caller(model, &msg, closure, output);
|
||||
roc__main_for_host_1_caller(model, &msg, closure, output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
extern fn roc__mainForHost_2_caller(ConstModel, [*]u8, *RocStr) void;
|
||||
extern fn roc__mainForHost_2_size() i64;
|
||||
extern fn roc__mainForHost_2_result_size() i64;
|
||||
extern fn roc__main_for_host_2_caller(ConstModel, [*]u8, *RocStr) void;
|
||||
extern fn roc__main_for_host_2_size() i64;
|
||||
extern fn roc__main_for_host_2_result_size() i64;
|
||||
|
||||
fn view(input: ConstModel) RocStr {
|
||||
const closure: [*]u8 = undefined;
|
||||
var output: RocStr = undefined;
|
||||
|
||||
roc__mainForHost_2_caller(input, closure, &output);
|
||||
roc__main_for_host_2_caller(input, closure, &output);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ comptime {
|
|||
const Unit = extern struct {};
|
||||
|
||||
pub export fn main() callconv(.C) u8 {
|
||||
const program = roc__mainForHost_1_exposed();
|
||||
const program = roc__main_for_host_1_exposed();
|
||||
|
||||
call_the_closure(program);
|
||||
|
||||
|
@ -206,7 +206,7 @@ fn call_the_closure(program: Program) void {
|
|||
return;
|
||||
}
|
||||
|
||||
pub export fn roc_fx_putInt(int: i64) i64 {
|
||||
pub export fn roc_fx_put_int(int: i64) i64 {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
stdout.print("{d}", .{int}) catch unreachable;
|
||||
|
@ -216,7 +216,7 @@ pub export fn roc_fx_putInt(int: i64) i64 {
|
|||
return 0;
|
||||
}
|
||||
|
||||
export fn roc_fx_putLine(rocPath: str.RocStr) callconv(.C) void {
|
||||
export fn roc_fx_put_line(rocPath: str.RocStr) callconv(.C) void {
|
||||
const stdout = std.io.getStdOut().writer();
|
||||
|
||||
for (rocPath.asSlice()) |char| {
|
||||
|
@ -234,14 +234,14 @@ const GetInt = extern struct {
|
|||
|
||||
comptime {
|
||||
if (@sizeOf(usize) == 8) {
|
||||
@export(roc_fx_getInt_64bit, .{ .name = "roc_fx_getInt" });
|
||||
@export(roc_fx_get_int_64bit, .{ .name = "roc_fx_get_int" });
|
||||
} else {
|
||||
@export(roc_fx_getInt_32bit, .{ .name = "roc_fx_getInt" });
|
||||
@export(roc_fx_get_int_32bit, .{ .name = "roc_fx_get_int" });
|
||||
}
|
||||
}
|
||||
|
||||
fn roc_fx_getInt_64bit() callconv(.C) GetInt {
|
||||
if (roc_fx_getInt_help()) |value| {
|
||||
fn roc_fx_get_int_64bit() callconv(.C) GetInt {
|
||||
if (roc_fx_get_int_help()) |value| {
|
||||
const get_int = GetInt{ .is_error = false, .value = value, .error_code = false };
|
||||
return get_int;
|
||||
} else |err| switch (err) {
|
||||
|
@ -256,8 +256,8 @@ fn roc_fx_getInt_64bit() callconv(.C) GetInt {
|
|||
return 0;
|
||||
}
|
||||
|
||||
fn roc_fx_getInt_32bit(output: *GetInt) callconv(.C) void {
|
||||
if (roc_fx_getInt_help()) |value| {
|
||||
fn roc_fx_get_int_32bit(output: *GetInt) callconv(.C) void {
|
||||
if (roc_fx_get_int_help()) |value| {
|
||||
const get_int = GetInt{ .is_error = false, .value = value, .error_code = false };
|
||||
output.* = get_int;
|
||||
} else |err| switch (err) {
|
||||
|
@ -272,7 +272,7 @@ fn roc_fx_getInt_32bit(output: *GetInt) callconv(.C) void {
|
|||
return;
|
||||
}
|
||||
|
||||
fn roc_fx_getInt_help() !i64 {
|
||||
fn roc_fx_get_int_help() !i64 {
|
||||
const stdin = std.io.getStdIn().reader();
|
||||
var buf: [40]u8 = undefined;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ platform "tui"
|
|||
exposes []
|
||||
packages {}
|
||||
imports []
|
||||
provides [mainForHost]
|
||||
provides [main_for_host]
|
||||
|
||||
mainForHost : { init : ({} -> Model) as Init, update : (Model, Str -> Model) as Update, view : (Model -> Str) as View }
|
||||
mainForHost = main
|
||||
main_for_host : { init : ({} -> Model) as Init, update : (Model, Str -> Model) as Update, view : (Model -> Str) as View }
|
||||
main_for_host = main
|
||||
|
|
|
@ -28,7 +28,7 @@ pub const MOD_APP: ModName = ModName(b"UserApp");
|
|||
pub const STATIC_STR_NAME: ConstName = ConstName(&Symbol::STR_ALIAS_ANALYSIS_STATIC.to_ne_bytes());
|
||||
pub const STATIC_LIST_NAME: ConstName = ConstName(b"THIS IS A STATIC LIST");
|
||||
|
||||
const DEFAULT_ENTRY_POINT_NAME: &[u8] = b"mainForHost";
|
||||
const DEFAULT_ENTRY_POINT_NAME: &[u8] = b"main_for_host";
|
||||
|
||||
pub fn func_name_bytes(proc: &Proc) -> [u8; SIZE] {
|
||||
let bytes = func_name_bytes_help(
|
||||
|
|
|
@ -144,7 +144,7 @@ pub const RocDec = extern struct {
|
|||
return (c -% 48) <= 9;
|
||||
}
|
||||
|
||||
pub fn toStr(self: RocDec) RocStr {
|
||||
pub fn to_str(self: RocDec) RocStr {
|
||||
// Special case
|
||||
if (self.num == 0) {
|
||||
return RocStr.init("0.0", 3);
|
||||
|
@ -1031,97 +1031,97 @@ test "fromStr: .123.1" {
|
|||
try expectEqual(dec, null);
|
||||
}
|
||||
|
||||
test "toStr: 100.00" {
|
||||
test "to_str: 100.00" {
|
||||
var dec: RocDec = .{ .num = 100000000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "100.0"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 123.45" {
|
||||
test "to_str: 123.45" {
|
||||
var dec: RocDec = .{ .num = 123450000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "123.45"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: -123.45" {
|
||||
test "to_str: -123.45" {
|
||||
var dec: RocDec = .{ .num = -123450000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "-123.45"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 123.0" {
|
||||
test "to_str: 123.0" {
|
||||
var dec: RocDec = .{ .num = 123000000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "123.0"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: -123.0" {
|
||||
test "to_str: -123.0" {
|
||||
var dec: RocDec = .{ .num = -123000000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "-123.0"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 0.45" {
|
||||
test "to_str: 0.45" {
|
||||
var dec: RocDec = .{ .num = 450000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "0.45"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: -0.45" {
|
||||
test "to_str: -0.45" {
|
||||
var dec: RocDec = .{ .num = -450000000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "-0.45"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 0.00045" {
|
||||
test "to_str: 0.00045" {
|
||||
var dec: RocDec = .{ .num = 450000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "0.00045"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: -0.00045" {
|
||||
test "to_str: -0.00045" {
|
||||
var dec: RocDec = .{ .num = -450000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "-0.00045"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: -111.123456" {
|
||||
test "to_str: -111.123456" {
|
||||
var dec: RocDec = .{ .num = -111123456000000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "-111.123456"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 123.1111111" {
|
||||
test "to_str: 123.1111111" {
|
||||
var dec: RocDec = .{ .num = 123111111100000000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "123.1111111"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 123.1111111111111 (big str)" {
|
||||
test "to_str: 123.1111111111111 (big str)" {
|
||||
var dec: RocDec = .{ .num = 123111111111111000000 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
errdefer res_roc_str.decref();
|
||||
defer res_roc_str.decref();
|
||||
|
||||
|
@ -1129,9 +1129,9 @@ test "toStr: 123.1111111111111 (big str)" {
|
|||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 123.111111111111444444 (max number of decimal places)" {
|
||||
test "to_str: 123.111111111111444444 (max number of decimal places)" {
|
||||
var dec: RocDec = .{ .num = 123111111111111444444 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
errdefer res_roc_str.decref();
|
||||
defer res_roc_str.decref();
|
||||
|
||||
|
@ -1139,9 +1139,9 @@ test "toStr: 123.111111111111444444 (max number of decimal places)" {
|
|||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 12345678912345678912.111111111111111111 (max number of digits)" {
|
||||
test "to_str: 12345678912345678912.111111111111111111 (max number of digits)" {
|
||||
var dec: RocDec = .{ .num = 12345678912345678912111111111111111111 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
errdefer res_roc_str.decref();
|
||||
defer res_roc_str.decref();
|
||||
|
||||
|
@ -1149,9 +1149,9 @@ test "toStr: 12345678912345678912.111111111111111111 (max number of digits)" {
|
|||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: std.math.maxInt" {
|
||||
test "to_str: std.math.maxInt" {
|
||||
var dec: RocDec = .{ .num = std.math.maxInt(i128) };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
errdefer res_roc_str.decref();
|
||||
defer res_roc_str.decref();
|
||||
|
||||
|
@ -1159,9 +1159,9 @@ test "toStr: std.math.maxInt" {
|
|||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: std.math.minInt" {
|
||||
test "to_str: std.math.minInt" {
|
||||
var dec: RocDec = .{ .num = std.math.minInt(i128) };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
errdefer res_roc_str.decref();
|
||||
defer res_roc_str.decref();
|
||||
|
||||
|
@ -1169,9 +1169,9 @@ test "toStr: std.math.minInt" {
|
|||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
}
|
||||
|
||||
test "toStr: 0" {
|
||||
test "to_str: 0" {
|
||||
var dec: RocDec = .{ .num = 0 };
|
||||
var res_roc_str = dec.toStr();
|
||||
var res_roc_str = dec.to_str();
|
||||
|
||||
const res_slice: []const u8 = "0.0"[0..];
|
||||
try expectEqualSlices(u8, res_slice, res_roc_str.asSlice());
|
||||
|
@ -1443,8 +1443,8 @@ pub fn fromStr(arg: RocStr) callconv(.C) num_.NumParseResult(i128) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn toStr(arg: RocDec) callconv(.C) RocStr {
|
||||
return @call(.always_inline, RocDec.toStr, .{arg});
|
||||
pub fn to_str(arg: RocDec) callconv(.C) RocStr {
|
||||
return @call(.always_inline, RocDec.to_str, .{arg});
|
||||
}
|
||||
|
||||
pub fn fromF64C(arg: f64) callconv(.C) i128 {
|
||||
|
|
|
@ -50,7 +50,7 @@ comptime {
|
|||
exportDecFn(dec.toF64, "to_f64");
|
||||
exportDecFn(dec.toI128, "to_i128");
|
||||
exportDecFn(dec.fromI128, "from_i128");
|
||||
exportDecFn(dec.toStr, "to_str");
|
||||
exportDecFn(dec.to_str, "to_str");
|
||||
|
||||
for (INTEGERS) |T| {
|
||||
dec.exportFromInt(T, ROC_BUILTINS ++ ".dec.from_int.");
|
||||
|
|
|
@ -199,8 +199,8 @@ import Result exposing [Result]
|
|||
## ends up having the type `U64`.
|
||||
##
|
||||
## Sometimes number literals don't become more specific. For example,
|
||||
## the `Num.toStr` function has the type `Num * -> Str`. This means that
|
||||
## when calling `Num.toStr(5 + 6)`, the expression `5 + 6`
|
||||
## the `Num.to_str` function has the type `Num * -> Str`. This means that
|
||||
## when calling `Num.to_str(5 + 6)`, the expression `5 + 6`
|
||||
## still has the type `Num *`. When this happens, `Num *` defaults to
|
||||
## being an [I64] - so this addition expression would overflow
|
||||
## if either 5 or 6 were replaced with a number big enough to cause
|
||||
|
@ -209,7 +209,7 @@ import Result exposing [Result]
|
|||
## If this default of [I64] is not big enough for your purposes,
|
||||
## you can add an `i128` to the end of the number literal, like so:
|
||||
## ```roc
|
||||
## Num.toStr(5_000_000_000i128)
|
||||
## Num.to_str(5_000_000_000i128)
|
||||
## ```
|
||||
## This `i128` suffix specifies that you want this number literal to be
|
||||
## an [I128] instead of a `Num *`. All the other numeric types have
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue