Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
key: ${{ runner.os }}-stack-${{ hashFiles('stack.yaml.lock') }}-${{ hashFiles('trypurescript.cabal') }}

- name: Build server code
run: stack --no-terminal -j1 build
run: stack --no-terminal build

- name: Build server assets
if: github.event_name == 'release'
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ New features:
Bugfixes:

Other improvements:
- Bump the Stackage resolver from `lts-20.9` to `lts-20.26` (GHC 9.2.5 → 9.2.8), the newest snapshot compatible with `purescript-0.15.15` (#322 by @thomashoneyman)
- Modernize the server build: `cabal-version: 2.4`, build with `-Wall -Werror` (with attendant cleanup in `server/Main.hs`), remove unused dependencies and the redundant `Setup.hs` (#322 by @thomashoneyman)
- Speed up CI server builds by removing the `-j1` limit; runners have had 4 vCPUs and 16GB of RAM for years (#322 by @thomashoneyman)
- Serve the site and the compiled `/output` modules with `Cache-Control: no-cache` so browsers revalidate via ETag instead of heuristically caching a stale client for months after a deploy (#322 by @thomashoneyman)

## [v2026-07-05.1](https://github.com/purescript/trypurescript/releases/tag/v2026-07-05.1)

Expand Down
2 changes: 0 additions & 2 deletions Setup.hs

This file was deleted.

8 changes: 8 additions & 0 deletions deploy/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ server {

location / {
root /var/www/trypurescript/public;
# Always revalidate (cheap ETag 304s): the HTML references the bundle by
# a fixed name, so without this browsers heuristically cache the site
# and can serve a stale client for months after a deploy.
add_header Cache-Control "no-cache";
}

}
Expand Down Expand Up @@ -86,6 +90,10 @@ server {
# match to ensure that we only serve JS files.
location ~ ^/output/(.+\.js)$ {
add_header Access-Control-Allow-Origin *;
# Module URLs are generated by the compiler and change content when the
# package set or compiler changes; revalidate so browsers never mix
# modules from different deploys.
add_header Cache-Control "no-cache";
alias /var/www/trypurescript/staging/.psci_modules/$1;
}
}
59 changes: 32 additions & 27 deletions server/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,22 @@

module Main (main) where

import Control.Monad (unless, foldM)
import Control.Monad.Error.Class (throwError)
import Control.Monad (foldM)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Logger (runLogger')
import qualified Control.Monad.State as State
import Control.Monad.Trans (lift)
import Control.Monad.Trans.Except (ExceptT(..), runExceptT)
import Control.Monad.Trans.Reader (runReaderT)
import Control.Monad.Writer.Strict (runWriterT)
import qualified Data.Aeson as A
import Data.Aeson ((.=))
import Data.Bifunctor (first, second, bimap)
import Data.Bifunctor (second, bimap)
import qualified Data.ByteString.Lazy as BL
import Data.Default (def)
import Data.Function (on)
import qualified Data.IORef as IORef
import Data.List (nubBy)
import qualified Data.List.NonEmpty as NE
import qualified Data.Map as M
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Text (Text)
import qualified Data.Text as T
Expand All @@ -50,6 +46,7 @@ import System.Environment (getArgs)
import System.Exit (exitFailure)
import System.FilePath.Glob (glob)
import qualified System.IO as IO
import Text.Read (readMaybe)
import Web.Scotty
import qualified Web.Scotty as Scotty

Expand Down Expand Up @@ -204,9 +201,9 @@ lookupAllConstructors env = P.everywhereOnTypesM $ \case
other -> pure other
where
lookupConstructor :: P.Environment -> P.ProperName 'P.TypeName -> [P.Qualified (P.ProperName 'P.TypeName)]
lookupConstructor env nm =
lookupConstructor env' nm =
[ q
| (q@(P.Qualified (N.ByModuleName _) thisNm), _) <- M.toList (P.types env)
| (q@(P.Qualified (N.ByModuleName _) thisNm), _) <- M.toList (P.types env')
, thisNm == nm
]

Expand All @@ -216,15 +213,15 @@ lookupAllConstructors env = P.everywhereOnTypesM $ \case
replaceTypeVariablesAndDesugar :: (Text -> Int -> P.SourceType) -> P.SourceType -> P.SourceType
replaceTypeVariablesAndDesugar f ty = State.evalState (P.everywhereOnTypesM go ty) (0, M.empty) where
go = \case
P.ParensInType _ ty -> pure ty
P.ParensInType _ inner -> pure inner
P.TypeVar _ s -> do
(next, m) <- State.get
(n, m) <- State.get
case M.lookup s m of
Nothing -> do
let ty = f s next
State.put (next + 1, M.insert s ty m)
pure ty
Just ty -> pure ty
let unknown = f s n
State.put (n + 1, M.insert s unknown m)
pure unknown
Just unknown -> pure unknown
other -> pure other

tryParseType :: Text -> Maybe P.SourceType
Expand All @@ -242,16 +239,24 @@ main :: IO ()
main = do
-- Stop mangled "Compiling ModuleName" text
IO.hSetBuffering IO.stderr IO.LineBuffering
(portString : inputGlobs) <- getArgs
let port = read portString
inputFiles <- concat <$> traverse glob inputGlobs
e <- runExceptT $ do
modules <- ExceptT $ I.loadAllModules inputFiles
(exts, env) <- ExceptT . I.runMake . I.make $ map (second CST.pureResult) modules
namesEnv <- fmap fst . runWriterT $ foldM P.externsEnv P.primEnv exts
let
allModuleNames = fmap (P.getModuleName . snd) modules
pure (allModuleNames, exts, namesEnv, env)
case e of
Left err -> print err >> exitFailure
Right (allModuleNames, exts, namesEnv, env) -> server allModuleNames exts namesEnv env port
args <- getArgs
case args of
portString : inputGlobs
| Just port <- readMaybe portString -> run port inputGlobs
_ -> do
IO.hPutStrLn IO.stderr "Usage: trypurescript PORT INPUT_GLOB..."
exitFailure
where
run :: Int -> [String] -> IO ()
run port inputGlobs = do
inputFiles <- concat <$> traverse glob inputGlobs
e <- runExceptT $ do
modules <- ExceptT $ I.loadAllModules inputFiles
(exts, env) <- ExceptT . I.runMake . I.make $ map (second CST.pureResult) modules
namesEnv <- fmap fst . runWriterT $ foldM P.externsEnv P.primEnv exts
let
allModuleNames = fmap (P.getModuleName . snd) modules
pure (allModuleNames, exts, namesEnv, env)
case e of
Left err -> print err >> exitFailure
Right (allModuleNames, exts, namesEnv, env) -> server allModuleNames exts namesEnv env port
9 changes: 6 additions & 3 deletions stack.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
resolver: lts-20.9
resolver: lts-20.26
packages:
- "."

Expand All @@ -8,8 +8,11 @@ extra-deps:
- process-1.6.13.1
# The Cabal library is not in Stackage
- Cabal-3.6.3.0
# Protolude is not yet in resolver snapshot
- protolude-0.3.1
# Protolude is not in the resolver snapshot; 0.3.3 (not 0.3.1) is needed
# for compatibility with the bytestring version in lts-20.26
- protolude-0.3.3
# purescript pins happy ==1.20.0, but lts-20.26 ships happy-1.20.1.1
- happy-1.20.0

flags:
these:
Expand Down
25 changes: 16 additions & 9 deletions stack.yaml.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file was autogenerated by Stack.
# You should not edit this file by hand.
# For more information, please see the documentation at:
# https://docs.haskellstack.org/en/stable/lock_files
# https://docs.haskellstack.org/en/stable/topics/lock_files

packages:
- completed:
Expand Down Expand Up @@ -33,15 +33,22 @@ packages:
original:
hackage: Cabal-3.6.3.0
- completed:
hackage: protolude-0.3.1@sha256:1cc9e5a5c26c33a43c52b554443dd9779fef13974eaa0beec7ca6d2551b400da,2647
hackage: protolude-0.3.3@sha256:0106615f6fe08de16fe512852c728797db17374d36b4a4ec8187563e924b2439,2261
pantry-tree:
sha256: 6452a6ca8d395f7d810139779bb0fd16fc1dbb00f1862630bc08ef5a100430f9
size: 1645
sha256: 174c107f3c3af1dc23330ff4431445830aac4b4fdba326e3e654eb491d6e9ca6
size: 1594
original:
hackage: protolude-0.3.1
hackage: protolude-0.3.3
- completed:
hackage: happy-1.20.0@sha256:5d47dc221a9fe964e36aaaa2e1ab7e8f085a225fd6528d6eff310b92360bbe99,5732
pantry-tree:
sha256: ff2e7df7cfe8746eedc6f69c225fa8c899c26d28f1c4964eeb00a5d757d30351
size: 8749
original:
hackage: happy-1.20.0
snapshots:
- completed:
sha256: c11fcbeb1aa12761044755b1109d16952ede2cb6147ebde777dd5cb38f784501
size: 649333
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/9.yaml
original: lts-20.9
sha256: 5a59b2a405b3aba3c00188453be172b85893cab8ebc352b1ef58b0eae5d248a2
size: 650475
url: https://raw.githubusercontent.com/commercialhaskell/stackage-snapshots/master/lts/20/26.yaml
original: lts-20.26
43 changes: 19 additions & 24 deletions trypurescript.cabal
Original file line number Diff line number Diff line change
@@ -1,41 +1,36 @@
cabal-version: 2.4
name: trypurescript
version: 1.0.0
cabal-version: >=1.8
build-type: Simple
license: BSD3
license: BSD-3-Clause
license-file: LICENSE
copyright: (c) Phil Freeman 2013
maintainer: paf31@cantab.net
synopsis: Interactive PureScript in the Browser
description: A simple web app for trying out the PureScript compiler
category: Web
author: Phil Freeman
data-dir: ""

executable trypurescript
-- Since no one depends on this project as a library,
-- packages below are `-any` because their versions are determined
-- by the `stack.yml` file. Versions correspond to the ones
-- specified in the resolver (i.e. the package set)
-- packages below are unbounded because their versions are
-- determined by the `stack.yaml` file. Versions correspond to the
-- ones specified in the resolver (i.e. the package set)
-- unless it is a versioned library added via `extra-deps` field.
build-depends: base -any,
aeson -any,
bytestring -any,
data-default -any,
directory -any,
filepath -any,
Glob -any,
scotty -any,
build-depends: base,
aeson,
bytestring,
containers,
data-default,
Glob,
mtl,
purescript,
containers -any,
http-types -any,
transformers -any,
mtl -any,
text -any,
time -any,
warp -any
scotty,
text,
time,
transformers,
warp
hs-source-dirs: server
main-is: Main.hs
buildable: True
other-modules: Main
ghc-options: -Werror -O2 -threaded -rtsopts
default-language: Haskell2010
ghc-options: -Wall -Werror -O2 -threaded -rtsopts
Loading