Skip to content

Commit

Permalink
Expand coverage and improve efficiency of Json.Decode kernel library
Browse files Browse the repository at this point in the history
+ Refactor JSON parser to improve runtime efficiency.
+ Add automated tests and productive implementation for float values in JSON.
  • Loading branch information
Viir committed Jan 19, 2025
1 parent 9288a08 commit 39d3635
Show file tree
Hide file tree
Showing 39 changed files with 1,070 additions and 786 deletions.
733 changes: 416 additions & 317 deletions implement/pine/Elm/elm-compiler/elm-kernel-modules/Json/Decode.elm

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Value
| StringValue String
| ArrayValue (List Value)
| ObjectValue (List ( String, Value ))
| FloatValue String


null : Value
Expand Down Expand Up @@ -65,6 +66,9 @@ encode indent value =
ObjectValue fields ->
"{" ++ String.join "," (List.map (encodeField indent) fields) ++ "}"

FloatValue asString ->
asString


encodeField : Int -> ( String, Value ) -> String
encodeField indent ( key, value ) =
Expand Down
153 changes: 83 additions & 70 deletions implement/pine/Elm/elm-compiler/elm-kernel-modules/String.elm
Original file line number Diff line number Diff line change
Expand Up @@ -340,104 +340,117 @@ endsWith pattern string =

toInt : String -> Maybe Int
toInt (String chars) =
toIntFromList chars
parseInt chars 0


fromInt : Int -> String
fromInt int =
String (fromIntAsList int)


toIntFromList : List Char -> Maybe Int
toIntFromList stringAsList =
parseInt : List Char -> Int -> Maybe Int
parseInt src offset0 =
let
firstChar =
Pine_kernel.head stringAsList
nextChar =
List.take 1 (List.drop offset0 src)
in
if Pine_kernel.equal [ firstChar, [] ] then
Nothing
case nextChar of
[ '-' ] ->
case parseUnsignedInt src (offset0 + 1) of
Just unsignedVal ->
Just -unsignedVal

else
let
( valueString, signMultiplier ) =
case firstChar of
'-' ->
( Pine_kernel.skip [ 1, stringAsList ], -1 )
Nothing ->
Nothing

'+' ->
( Pine_kernel.skip [ 1, stringAsList ], 1 )
[ '+' ] ->
parseUnsignedInt src (offset0 + 1)

_ ->
( stringAsList, 1 )
in
if Pine_kernel.equal [ valueString, [] ] then
Nothing
_ ->
-- If no minus sign, parse the rest as an unsigned integer
parseUnsignedInt src offset0

else
case toUnsignedIntFromList 0 valueString of
Just unsigned ->
Just (Pine_kernel.int_mul [ signMultiplier, unsigned ])

Nothing ->
Nothing
parseUnsignedInt : List Char -> Int -> Maybe Int
parseUnsignedInt src offset0 =
case List.take 1 (List.drop offset0 src) of
[ '0' ] ->
if Pine_kernel.equal [ Pine_kernel.length src, offset0 + 1 ] then
Just 0

else
Nothing

toUnsignedIntFromList : Int -> List Char -> Maybe Int
toUnsignedIntFromList upper chars =
let
char =
Pine_kernel.head chars
in
if Pine_kernel.equal [ char, [] ] then
Just upper
[ '1' ] ->
parseUnsignedIntRec 1 src (offset0 + 1)

else
case digitValueFromChar char of
Nothing ->
Nothing
[ '2' ] ->
parseUnsignedIntRec 2 src (offset0 + 1)

Just digitValue ->
toUnsignedIntFromList
(Pine_kernel.int_add [ digitValue, Pine_kernel.int_mul [ upper, 10 ] ])
(Pine_kernel.skip [ 1, chars ])
[ '3' ] ->
parseUnsignedIntRec 3 src (offset0 + 1)

[ '4' ] ->
parseUnsignedIntRec 4 src (offset0 + 1)

digitValueFromChar : Char -> Maybe Int
digitValueFromChar char =
case char of
'0' ->
Just 0
[ '5' ] ->
parseUnsignedIntRec 5 src (offset0 + 1)

'1' ->
Just 1
[ '6' ] ->
parseUnsignedIntRec 6 src (offset0 + 1)

'2' ->
Just 2
[ '7' ] ->
parseUnsignedIntRec 7 src (offset0 + 1)

'3' ->
Just 3
[ '8' ] ->
parseUnsignedIntRec 8 src (offset0 + 1)

'4' ->
Just 4
[ '9' ] ->
parseUnsignedIntRec 9 src (offset0 + 1)

'5' ->
Just 5
_ ->
Nothing

'6' ->
Just 6

'7' ->
Just 7
parseUnsignedIntRec : Int -> List Char -> Int -> Maybe Int
parseUnsignedIntRec upper src offset0 =
case List.take 1 (List.drop offset0 src) of
[ '0' ] ->
parseUnsignedIntRec (upper * 10) src (offset0 + 1)

'8' ->
Just 8
[ '1' ] ->
parseUnsignedIntRec (upper * 10 + 1) src (offset0 + 1)

'9' ->
Just 9
[ '2' ] ->
parseUnsignedIntRec (upper * 10 + 2) src (offset0 + 1)

_ ->
[ '3' ] ->
parseUnsignedIntRec (upper * 10 + 3) src (offset0 + 1)

[ '4' ] ->
parseUnsignedIntRec (upper * 10 + 4) src (offset0 + 1)

[ '5' ] ->
parseUnsignedIntRec (upper * 10 + 5) src (offset0 + 1)

[ '6' ] ->
parseUnsignedIntRec (upper * 10 + 6) src (offset0 + 1)

[ '7' ] ->
parseUnsignedIntRec (upper * 10 + 7) src (offset0 + 1)

[ '8' ] ->
parseUnsignedIntRec (upper * 10 + 8) src (offset0 + 1)

[ '9' ] ->
parseUnsignedIntRec (upper * 10 + 9) src (offset0 + 1)

[ _ ] ->
Nothing

_ ->
Just upper


fromIntAsList : Int -> List Char
fromIntAsList int =
Expand Down Expand Up @@ -804,7 +817,7 @@ toRationalComponentsLessSign chars =
Nothing

[ String whole ] ->
case toUnsignedIntFromList 0 whole of
case parseUnsignedInt whole 0 of
Nothing ->
Nothing

Expand All @@ -817,20 +830,20 @@ toRationalComponentsLessSign chars =
Nothing

else
case toUnsignedIntFromList 0 beforeSep of
case parseUnsignedIntRec 0 beforeSep 0 of
Nothing ->
Nothing

Just beforeSepInt ->
Just (Elm_Float beforeSepInt 1)

else
case toUnsignedIntFromList 0 beforeSep of
case parseUnsignedIntRec 0 beforeSep 0 of
Nothing ->
Nothing

Just beforeSepInt ->
case toUnsignedIntFromList 0 afterSep of
case parseUnsignedIntRec 0 afterSep 0 of
Nothing ->
Nothing

Expand Down
Loading

0 comments on commit 39d3635

Please sign in to comment.