ihp icon indicating copy to clipboard operation
ihp copied to clipboard

HSX Template compiling lambda functions

Open Montmorency opened this issue 3 years ago • 2 comments

On upgrade to v0.20 some old hsx code with a lambda expression stopped compiling: Old code:

     <input type="hidden" name="googlePlaceId" value={(\(PlaceId x) -> x)(place_id x)}/>

Error message:



 • Exception when trying to run compile-time code:
        IHP.HSX.HsExpToTH.toPat: not implemented: (PlaceId x)
CallStack (from HasCallStack):
  error, called at ./IHP/HSX/HsExpToTH.hs:195:18 in ihp-hsx-0.18.0-5G7n5wCYmB1CeYaNqV7khQ:IHP.HSX.HsExpToTH
      Code: Language.Haskell.TH.Quote.quoteExp
              hsx
              "\n\
              \                                 <div id=\"google-result\" data-lat-lon={encode $ (location (geometry x))}>  {formatted_address x} </div>\n\
              \                                 <input type=\"hidden\" name=\"eircode\" value={eircode} />\n\
              \                                 <input type=\"hidden\" name=\"geoCoords\" value={latlngParam x}/>\n\
              \                                 <input type=\"hidden\" name=\"googlePlaceId\" value={(\\(PlaceId x) -> x)(place_id x)}/>\n\
              \                                 <input type=\"hidden\" name=\"googleMapsJSON\" value={encode x}/>\n\
              \                                 {siteNameInputField sitename}\n\
              \                                 {submitButton {label=\"Confirm Location\"}}\n\

Fix: Move lambda expression out of HSX block and into where clause.

Also some selectField code no longer compiling:

{(selectField #goal (Nothing:userGoals)){disableLabel=True}}

Montmorency avatar Aug 30 '22 12:08 Montmorency

Also ran into this issue:

renderForm :: Product -> Html
renderForm product = formFor product [hsx|
    {(textField #name) { placeholder = "Product Model Name", required = True }}

    {(textareaField #description) { labelClass = "font-medium text-gray-700", placeholder = "Short Generic Description" }}

    {(selectField #category (Nothing:(map Just productCategories)))}

    {(selectField #productManufacturerId (Nothing:(map Just manufacturers)))}

    {(checkboxField #public) { fieldLabel = "Visible On Website?" }}

    {(submitButton) { label = "Update" }}
|]

Error message:

Rebuilding...
[76 of 80] Compiling Admin.View.Products.New ( Admin/View/Products/New.hs, interpreted )
Done in 26ms.

Admin/View/Products/New.hs:28:50: error:
    * Exception when trying to run compile-time code:
        exact
CallStack (from HasCallStack):
  error, called at ./IHP/HSX/HsExpToTH.hs:67:16 in ihp-hsx-0.18.0-5G7n5wCYmB1CeYaNqV7khQ:IHP.HSX.HsExpToTH
      Code: Language.Haskell.TH.Quote.quoteExp
              hsx
              "\n\
              \                {(textField #name) { placeholder = \"Product Model Name\", required = True }}\n\
              \\n\
              \                {(textareaField #description) { labelClass = \"font-medium text-gray-700\", placeholder = \"Short Generic Description\" }}\n\
              \\n\
              \                {(selectField #category (Nothing:(map Just productCategories)))}\n\
              \\n\
              \                {(selectField #productManufacturerId (Nothing:(map Just manufacturers)))}\n\
              \\n\
              \                {(checkboxField #public) { fieldLabel = \"Visible On Website?\" }}\n\
              \\n\
              \                {(submitButton) { label = \"Create\" }}\n\
              \            "
    * In the quasi-quotation:
        [hsx|
                {(textField #name) { placeholder = "Product Model Name", required = True }}

                {(textareaField #description) { labelClass = "font-medium text-gray-700", placeholder = "Short Generic Description" }}

                {(selectField #category (Nothing:(map Just productCategories)))}

                {(selectField #productManufacturerId (Nothing:(map Just manufacturers)))}

                {(checkboxField #public) { fieldLabel = "Visible On Website?" }}

                {(submitButton) { label = "Create" }}
            |]
   |
28 |             renderForm product = formFor product [hsx|
   |                                                  ^^^^^...
[77 of 80] Compiling Admin.View.Products.Edit ( Admin/View/Products/Edit.hs, interpreted )

Admin/View/Products/Edit.hs:30:38: error:
    * Exception when trying to run compile-time code:
        exact
CallStack (from HasCallStack):
  error, called at ./IHP/HSX/HsExpToTH.hs:67:16 in ihp-hsx-0.18.0-5G7n5wCYmB1CeYaNqV7khQ:IHP.HSX.HsExpToTH
      Code: Language.Haskell.TH.Quote.quoteExp
              hsx
              "\n\
              \    {(textField #name) { placeholder = \"Product Model Name\", required = True }}\n\
              \\n\
              \    {(textareaField #description) { labelClass = \"font-medium text-gray-700\", placeholder = \"Short Generic Description\" }}\n\
              \\n\
              \    {(selectField #category (Nothing:(map Just productCategories)))}\n\
              \\n\
              \    {(selectField #productManufacturerId (Nothing:(map Just manufacturers)))}\n\
              \\n\
              \    {(checkboxField #public) { fieldLabel = \"Visible On Website?\" }}\n\
              \\n\
              \    {(submitButton) { label = \"Update\" }}\n"
    * In the quasi-quotation:
        [hsx|
    {(textField #name) { placeholder = "Product Model Name", required = True }}

    {(textareaField #description) { labelClass = "font-medium text-gray-700", placeholder = "Short Generic Description" }}

    {(selectField #category (Nothing:(map Just productCategories)))}

    {(selectField #productManufacturerId (Nothing:(map Just manufacturers)))}

    {(checkboxField #public) { fieldLabel = "Visible On Website?" }}

    {(submitButton) { label = "Update" }}
|]
   |
30 | renderForm product = formFor product [hsx|
   |                                      ^^^^^...
Failed, 75 modules loaded.

Working code:

renderForm :: Product -> Html
renderForm product = formFor product [hsx|
    {(textField #name) { placeholder = "Product Model Name", required = True }}

    {(textareaField #description) { labelClass = "font-medium text-gray-700", placeholder = "Short Generic Description" }}

    {(selectField #category ([Nothing] ++ map Just productCategories))}

    {(selectField #productManufacturerId ([Nothing] ++ map Just manufacturers))}

    {(checkboxField #public) { fieldLabel = "Visible On Website?" }}

    {(submitButton) { label = "Update" }}
|]

s0kil avatar Aug 31 '22 16:08 s0kil

Working on this in branch A lot of type familes make it tricky to find the right mapping (ConPat -> Th.ConP).

The target code to get working is an infix list concatenation and a parenthesies wrapped data constructor for pattern matching with lambdas.

    html WelcomeView = [hsx|
                            <p> <a href={NewSessionAction}> Login </a> </p>
                            <p> <a href={DeleteSessionAction}> Logout </a> </p>
                            { renderGreetAdmin currentAdminOrNothing }

                            <form>
                            <!-- These work  -->
                            {infixList}
                            <input type="hidden" name="googlePlaceId" value={unpackedPlaceData}/>

                            <!-- These don't -->
<!--                             {1 : [2,3,42]} -->
                            <input type="hidden" name="googlePlaceId" value={(\(PlaceId x) -> x)(placeData)}/>
                            </form>
                       |]
                        where
                            placeData = PlaceId "Punches Cross"
                            infixList = (1 ::Int) : [2,3,42]
                            unpackedPlaceData = (\(PlaceId x) -> x) placeData

Montmorency avatar Sep 26 '22 10:09 Montmorency

Fixed via https://github.com/digitallyinduced/ihp/pull/1535

mpscholten avatar Sep 27 '22 08:09 mpscholten