Skip to content
This repository has been archived by the owner on Oct 5, 2024. It is now read-only.

[wip] Add support for lists #39

Merged
merged 28 commits into from
Jul 11, 2019
Merged

[wip] Add support for lists #39

merged 28 commits into from
Jul 11, 2019

Conversation

Warry
Copy link
Contributor

@Warry Warry commented Jul 8, 2019

fixes #27

src/compiler/AST/Frontend.elm Outdated Show resolved Hide resolved
List { list } ->
"["
++ (List.map emitExpr list |> String.join ", ")
++ "]"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Official elm represents lists as linked lists rather than javascript arrays which makes concatenation work. I suspect that elm-in-elm should follow the same approach

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly official Elm keeps list literals as Lists of the language it's defined in (see AST.Source, AST.Canonical, AST.Optimized) and when emitting JS (Generate.JavaScript.Expression) either returns Nil or calls fromArray and generates a JS list as an argument for it.

We'll definitely have to plug into the elm/core List definition (btw funny thing, it's JS-only 😭 ), but we can do that later. What @Warry has right now is not that far off, and for now good enough I think. When we have enough stuff working that it stops being consistent with each other, we'll fix it.

WDYT @harrysarson @Warry ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is interesting, also interesting why the list definition is in javascript.

Regarding long term plan sounds good - the point at which it stops working will probably be when we implement (::).

@harrysarson
Copy link
Contributor

Looks nice!

@Warry
Copy link
Contributor Author

Warry commented Jul 8, 2019

To clarify: I toyed around to get to understand what I'm touching. The given assignment doesn't cover parsing, so it'll be deleted.
My plan this evening:

  • Seek what errors the elm compiler references
  • Write code that cover more cases, including breaking
  • Adding tests for the Type Inference stage

@Janiczek
Copy link
Contributor

Janiczek commented Jul 8, 2019

@Warry if you want to do everything in one go (ie. with parsers included), feel free to; I've just separated the issues as I think that would be more helpful (smaller problems) for newcomers. If you want to do parsers with the rest of the stuff, I won't mind.

src/compiler/Error.elm Outdated Show resolved Hide resolved
Type.List type1 ->
List.foldl
(\(entry, type2) acc ->
(equals type1 type2) :: acc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd just change the names a bit:

  • type1 is listParamType
  • entry we don't care about ➡️ _
  • type2 can be listElementType
  • and acc is equations or eqs?

Anyway that's how I'd write it. 😅

++ Type.toString t2
++ " don't match."
_ ->
"wft"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably just use Error.toString? 🙈

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes! The state of that PR is a mess, I won't leave it that way very long ^^ I guess I just have to Error.toString Error.TypeError typeError.

tests/ParserTest.elm Outdated Show resolved Hide resolved
)
, ( "more items types"
, Canonical.List [ Canonical.Literal (Int 2), Canonical.Literal (Int 3), Canonical.Literal (Bool False) ]
, Err (Error.TypeMismatch (Type.Int) (Type.Bool))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some extra parentheses, I expect running elm-format would solve those

tests/InferTypesTest.elm Outdated Show resolved Hide resolved
)
, ( "simple list2"
, List [ typed (Literal (String "one")), typed (Literal (Int 2)), typed (Literal (Int 3)) ]
, "[\"one\", 2, 3]"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd drop this test as that source Expr is a bit nonsensical. Or let's change it to a list of three strings?

, item = PP.subExpression 0 config
, trailing = P.Forbidden
}
|> P.inContext InList
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool to see P.sequence works well. I'm a bit careful regarding those helpers 😅

Copy link
Contributor Author

@Warry Warry Jul 11, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not perfect, but I guess it was specifically design with that usecase in mind, so I'm confident it can stay like this until perfs become a thing or at least until (::).

src/compiler/Error.elm Outdated Show resolved Hide resolved
src/compiler/Error.elm Outdated Show resolved Hide resolved
@@ -66,6 +66,11 @@ emitExpr ( expr, _ ) =
in
"((() => {" ++ bindingsJS ++ "; return " ++ emitExpr body ++ ";})())"

List list_ ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again list_ -> items or list 😄

@@ -170,3 +170,21 @@ assignIdsWith idSource expr =

Canonical.Unit ->
wrap idSource Typed.Unit

Canonical.List list_ ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aand again list_ -> items or list. Seeing as the rest of the function uses items_, I guess items makes most sense here.

desugarList : (Frontend.Expr -> Result DesugarError Canonical.Expr) -> List Frontend.Expr -> Result DesugarError Canonical.Expr
desugarList recurse list =
List.map recurse list
|> List.foldl (Result.map2 (::)) (Ok [])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some Debug.logs:

source:           [ 1, 50, 999 ]
after parsing:    List [Literal (Int 1),Literal (Int 50),Literal (Int 999)]
after desugaring: List [Literal (Int 999),Literal (Int 50),Literal (Int 1)]
after typing:     (List [(Literal (Int 999),Int),(Literal (Int 50),Int),(Literal (Int 1),Int)],Var 4)
after emit:       [999, 50, 1]

I believe the foldr was correct. The comment below was just a question of why is the foldr there, didn't want to indicate that it's wrong ... :) sorry for confusion!

Copy link
Contributor

@Janiczek Janiczek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@Janiczek Janiczek merged commit c6ffb45 into elm-in-elm:master Jul 11, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for lists
3 participants