From d8ae362bb7efaf786f447ad2e2450ee057806716 Mon Sep 17 00:00:00 2001 From: Mario Rogic Date: Mon, 11 Sep 2023 13:14:42 +0100 Subject: [PATCH 01/34] llvm@13 fixes local M1 build, try on buildserver https://github.com/haskell-crypto/cryptonite/issues/372#issuecomment-1397529056 --- .github/workflows/build-macos-arm64.yml | 2 +- .github/workflows/build-macos-x86_64.yml | 1 - distribution/build-macos-arm64.sh | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-macos-arm64.yml b/.github/workflows/build-macos-arm64.yml index d0810883..3685b8c2 100644 --- a/.github/workflows/build-macos-arm64.yml +++ b/.github/workflows/build-macos-arm64.yml @@ -22,6 +22,6 @@ jobs: - name: Run distribution script run: | test -x "$(which ghcup)" && curl https://downloads.haskell.org/~ghcup/aarch64-apple-darwin-ghcup -o ~/.local/bin/ghcup && chmod a+x ~/.local/bin/ghcup - brew install llvm@12 + brew install llvm@13 cd distribution ./build-macos-arm64.sh diff --git a/.github/workflows/build-macos-x86_64.yml b/.github/workflows/build-macos-x86_64.yml index aa4c09d0..2e084b6f 100644 --- a/.github/workflows/build-macos-x86_64.yml +++ b/.github/workflows/build-macos-x86_64.yml @@ -22,6 +22,5 @@ jobs: - name: Run distribution script run: | test -x "$(which ghcup)" && curl https://downloads.haskell.org/~ghcup/aarch64-apple-darwin-ghcup -o ~/.local/bin/ghcup && chmod a+x ~/.local/bin/ghcup - brew install llvm@12 cd distribution ./build-macos-x86_64.sh diff --git a/distribution/build-macos-arm64.sh b/distribution/build-macos-arm64.sh index 7585ad1e..257a417b 100755 --- a/distribution/build-macos-arm64.sh +++ b/distribution/build-macos-arm64.sh @@ -36,7 +36,7 @@ git submodule init && git submodule update ffiLibs="$(xcrun --show-sdk-path)/usr/include/ffi" # Workaround for GHC9.0.2 bug until we can use GHC9.2.3+ export C_INCLUDE_PATH=$ffiLibs # https://gitlab.haskell.org/ghc/ghc/-/issues/20592#note_436353 -export PATH="/opt/homebrew/opt/llvm@12/bin:$PATH" # The arm64 build currently requires llvm until we get to GHC 9.4+ +export PATH="/opt/homebrew/opt/llvm@13/bin:$PATH" # The arm64 build currently requires llvm until we get to GHC 9.4+ $stack install --local-bin-path $dist From 15a70693905f2a53c2ed7361e2f822c050990638 Mon Sep 17 00:00:00 2001 From: Mario Rogic Date: Thu, 14 Sep 2023 21:36:33 +0100 Subject: [PATCH 02/34] Patch in repl API functionality for elm-notebook exploration --- elm.cabal | 4 + extra/Artifacts.hs | 155 +++++++++++++++++++++++++ extra/Cors.hs | 48 ++++++++ extra/Endpoint/Repl.hs | 246 ++++++++++++++++++++++++++++++++++++++++ outlines/repl/elm.json | 19 ++++ repl-src/.keep | 0 terminal/src/Develop.hs | 8 ++ test/Test.hs | 4 +- 8 files changed, 483 insertions(+), 1 deletion(-) create mode 100644 extra/Artifacts.hs create mode 100644 extra/Cors.hs create mode 100644 extra/Endpoint/Repl.hs create mode 100644 outlines/repl/elm.json create mode 100644 repl-src/.keep diff --git a/elm.cabal b/elm.cabal index 276c1592..5c2f4a4e 100644 --- a/elm.cabal +++ b/elm.cabal @@ -309,6 +309,9 @@ Executable lamdera Test.Wire Lamdera.Evergreen.TestMigrationHarness Lamdera.Evergreen.TestMigrationGenerator + Endpoint.Repl + Artifacts + Cors -- Debug helpers -- @@ -397,6 +400,7 @@ Executable lamdera -- Debug unicode-show, network-info, + network-uri, -- Future conduit-extra, diff --git a/extra/Artifacts.hs b/extra/Artifacts.hs new file mode 100644 index 00000000..0a03f52a --- /dev/null +++ b/extra/Artifacts.hs @@ -0,0 +1,155 @@ +{-# OPTIONS_GHC -Wall #-} +module Artifacts + ( Artifacts(..) + , loadCompile + , loadRepl + , toDepsInfo + ) + where + + +import Control.Concurrent (readMVar) +import Control.Monad (liftM2) +import qualified Data.ByteString as BS +import qualified Data.ByteString.Builder as B +import qualified Data.ByteString.Lazy as LBS +import qualified Data.Map as Map +import qualified Data.Name as N +import qualified Data.OneOrMore as OneOrMore +import qualified System.Directory as Dir +import System.FilePath (()) + +import qualified AST.Canonical as Can +import qualified AST.Optimized as Opt +import qualified BackgroundWriter as BW +import qualified Elm.Details as Details +import qualified Elm.Interface as I +import qualified Elm.ModuleName as ModuleName +import qualified Elm.Package as Pkg +import Json.Encode ((==>)) +import qualified Json.Encode as E +import qualified Json.String as Json +import qualified Reporting + + + +-- ARTIFACTS + + +data Artifacts = + Artifacts + { _ifaces :: Map.Map ModuleName.Raw I.Interface + , _graph :: Opt.GlobalGraph + } + + +loadCompile :: IO Artifacts +loadCompile = + load ("outlines" "compile") + + +loadRepl :: IO Artifacts +loadRepl = + load ("outlines" "repl") + + + +-- LOAD + + +load :: FilePath -> IO Artifacts +load dir = + BW.withScope $ \scope -> + do putStrLn $ "Loading " ++ dir "elm.json" + style <- Reporting.terminal + root <- fmap ( dir) Dir.getCurrentDirectory + result <- Details.load style scope root + case result of + Left _ -> + error $ "Ran into some problem loading elm.json\nTry running `lamdera make` in: " ++ dir + + Right details -> + do omvar <- Details.loadObjects root details + imvar <- Details.loadInterfaces root details + mdeps <- readMVar imvar + mobjs <- readMVar omvar + case liftM2 (,) mdeps mobjs of + Nothing -> + error $ "Ran into some weird problem loading elm.json\nTry running `lamdera make` in: " ++ dir + + Just (deps, objs) -> + return $ Artifacts (toInterfaces deps) objs + + +toInterfaces :: Map.Map ModuleName.Canonical I.DependencyInterface -> Map.Map ModuleName.Raw I.Interface +toInterfaces deps = + Map.mapMaybe toUnique $ Map.fromListWith OneOrMore.more $ + Map.elems (Map.mapMaybeWithKey getPublic deps) + + +getPublic :: ModuleName.Canonical -> I.DependencyInterface -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore I.Interface) +getPublic (ModuleName.Canonical _ name) dep = + case dep of + I.Public iface -> Just (name, OneOrMore.one iface) + I.Private _ _ _ -> Nothing + + +toUnique :: OneOrMore.OneOrMore a -> Maybe a +toUnique oneOrMore = + case oneOrMore of + OneOrMore.One value -> Just value + OneOrMore.More _ _ -> Nothing + + + +-- TO DEPS INFO + + +toDepsInfo :: Artifacts -> BS.ByteString +toDepsInfo (Artifacts ifaces _) = + LBS.toStrict $ B.toLazyByteString $ E.encodeUgly $ encode ifaces + + + +-- ENCODE + + +encode :: Map.Map ModuleName.Raw I.Interface -> E.Value +encode ifaces = + E.dict Json.fromName encodeInterface ifaces + + +encodeInterface :: I.Interface -> E.Value +encodeInterface (I.Interface pkg values unions aliases binops) = + E.object + [ "pkg" ==> E.chars (Pkg.toChars pkg) + , "ops" ==> E.list E.name (Map.keys binops) + , "values" ==> E.list E.name (Map.keys values) + , "aliases" ==> E.list E.name (Map.keys (Map.filter isPublicAlias aliases)) + , "types" ==> E.dict Json.fromName (E.list E.name) (Map.mapMaybe toPublicUnion unions) + ] + + +isPublicAlias :: I.Alias -> Bool +isPublicAlias alias = + case alias of + I.PublicAlias _ -> True + I.PrivateAlias _ -> False + + +toPublicUnion :: I.Union -> Maybe [N.Name] +toPublicUnion union = + case union of + I.OpenUnion (Can.Union _ variants _ _) -> + Just (map getVariantName variants) + + I.ClosedUnion _ -> + Just [] + + I.PrivateUnion _ -> + Nothing + + +getVariantName :: Can.Ctor -> N.Name +getVariantName (Can.Ctor name _ _ _) = + name diff --git a/extra/Cors.hs b/extra/Cors.hs new file mode 100644 index 00000000..e33b2f1f --- /dev/null +++ b/extra/Cors.hs @@ -0,0 +1,48 @@ +{-# OPTIONS_GHC -Wall #-} +module Cors + ( allow + ) + where + + +import qualified Data.HashSet as HashSet +import Network.URI (parseURI) +import Snap.Core (Snap, Method, method) +import Snap.Util.CORS (CORSOptions(..), HashableMethod(..), OriginList(Origins), applyCORS, mkOriginSet) + + + +-- ALLOW + + +allow :: Method -> [String] -> Snap () -> Snap () +allow method_ origins snap = + applyCORS (toOptions method_ origins) $ method method_ $ + snap + + + +-- TO OPTIONS + + +toOptions :: (Monad m) => Method -> [String] -> CORSOptions m +toOptions method_ origins = + let + allowedOrigins = toOriginList origins + allowedMethods = HashSet.singleton (HashableMethod method_) + in + CORSOptions + { corsAllowOrigin = return allowedOrigins + , corsAllowCredentials = return True + , corsExposeHeaders = return HashSet.empty + , corsAllowedMethods = return allowedMethods + , corsAllowedHeaders = return + } + + +toOriginList :: [String] -> OriginList +toOriginList origins = + Origins $ mkOriginSet $ + case traverse parseURI origins of + Just uris -> uris + Nothing -> error "invalid entry given to toOriginList list" diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs new file mode 100644 index 00000000..84220846 --- /dev/null +++ b/extra/Endpoint/Repl.hs @@ -0,0 +1,246 @@ +{-# OPTIONS_GHC -Wall #-} +{-# LANGUAGE OverloadedStrings #-} +module Endpoint.Repl + ( endpoint + ) + where + + +import Data.Aeson ((.:)) +import qualified Data.Aeson as Aeson +import qualified Data.Aeson.Types as Aeson +import qualified Data.ByteString as BS +import qualified Data.ByteString.Builder as B +import qualified Data.ByteString.Lazy as LBS +import qualified Data.Map as Map +import Data.Map ((!)) +import qualified Data.Map.Utils as Map +import qualified Data.Name as N +import qualified Data.NonEmptyList as NE +import Snap.Core + +import qualified Artifacts as A +import qualified Cors + +import qualified AST.Source as Src +import qualified AST.Canonical as Can +import qualified AST.Optimized as Opt +import qualified Compile +import qualified Elm.Interface as I +import qualified Elm.ModuleName as ModuleName +import qualified Elm.Package as Pkg +import qualified File +import qualified Generate.JavaScript as JS +import qualified Json.Encode as Encode +import qualified Parse.Module as Parse +import qualified Repl +import qualified Reporting.Annotation as A +import qualified Reporting.Error as Error +import qualified Reporting.Error.Import as Import +import qualified Reporting.Exit as Exit +import qualified Reporting.Exit.Help as Help +import qualified Reporting.Render.Type.Localizer as L + + + +-- ALLOWED ORIGINS + + +allowedOrigins :: [String] +allowedOrigins = + [ "*" + ] + + + +-- ENDPOINT + + +endpoint :: A.Artifacts -> Snap () +endpoint artifacts = + Cors.allow POST allowedOrigins $ + do body <- readRequestBody (64 * 1024) + case decodeBody body of + Just (state, entry) -> + serveOutcome (toOutcome artifacts state entry) + + Nothing -> + do modifyResponse $ setResponseStatus 400 "Bad Request" + modifyResponse $ setContentType "text/html; charset=utf-8" + writeBS "Received unexpected JSON body." + + + +-- TO OUTCOME + + +data Outcome + = NewImport N.Name + | NewType N.Name + | NewWork B.Builder + -- + | Skip + | Indent + | DefStart N.Name + -- + | NoPorts + | InvalidCommand + | Failure BS.ByteString Error.Error + + +toOutcome :: A.Artifacts -> Repl.State -> String -> Outcome +toOutcome artifacts state entry = + case reverse (lines entry) of + [] -> + Skip + + prev : rev -> + case Repl.categorize (Repl.Lines prev rev) of + Repl.Done input -> + case input of + Repl.Import name src -> compile artifacts state (ImportEntry name src) + Repl.Type name src -> compile artifacts state (TypeEntry name src) + Repl.Decl name src -> compile artifacts state (DeclEntry name src) + Repl.Expr src -> compile artifacts state (ExprEntry src) + Repl.Port -> NoPorts + Repl.Skip -> Skip + Repl.Reset -> InvalidCommand + Repl.Exit -> InvalidCommand + Repl.Help _ -> InvalidCommand + + Repl.Continue prefill -> + case prefill of + Repl.Indent -> Indent + Repl.DefStart name -> DefStart name + + + +-- SERVE OUTCOME + + +serveOutcome :: Outcome -> Snap () +serveOutcome outcome = + let + serveString = serveBuilder "text/plain" + in + case outcome of + NewImport name -> serveString $ "add-import:" <> N.toBuilder name + NewType name -> serveString $ "add-type:" <> N.toBuilder name + NewWork js -> serveBuilder "application/javascript" js + Skip -> serveString $ "skip" + Indent -> serveString $ "indent" + DefStart name -> serveString $ "def-start:" <> N.toBuilder name + NoPorts -> serveString $ "no-ports" + InvalidCommand -> serveString $ "invalid-command" + Failure source err -> + serveBuilder "application/json" $ Encode.encodeUgly $ Exit.toJson $ + Help.compilerReport "/" (Error.Module N.replModule "/repl" File.zeroTime source err) [] + + +serveBuilder :: BS.ByteString -> B.Builder -> Snap () +serveBuilder mime builder = + do modifyResponse (setContentType mime) + writeBuilder builder + + + +-- COMPILE + + +data EntryType + = ImportEntry N.Name BS.ByteString + | TypeEntry N.Name BS.ByteString + | DeclEntry N.Name BS.ByteString + | ExprEntry BS.ByteString + + +compile :: A.Artifacts -> Repl.State -> EntryType -> Outcome +compile (A.Artifacts interfaces objects) state@(Repl.State imports types decls) entryType = + let + source = + case entryType of + ImportEntry name src -> Repl.toByteString (state { Repl._imports = Map.insert name (B.byteString src) imports }) Repl.OutputNothing + TypeEntry name src -> Repl.toByteString (state { Repl._types = Map.insert name (B.byteString src) types }) Repl.OutputNothing + DeclEntry name src -> Repl.toByteString (state { Repl._decls = Map.insert name (B.byteString src) decls }) (Repl.OutputDecl name) + ExprEntry src -> Repl.toByteString state (Repl.OutputExpr src) + in + case + do modul <- mapLeft Error.BadSyntax $ Parse.fromByteString Parse.Application source + ifaces <- mapLeft Error.BadImports $ checkImports interfaces (Src._imports modul) + artifacts <- Compile.compile Pkg.dummyName ifaces modul + return ( modul, artifacts, objects ) + of + Left err -> + Failure source err + + Right info -> + case entryType of + ImportEntry name _ -> NewImport name + TypeEntry name _ -> NewType name + DeclEntry name _ -> NewWork (toJavaScript info (Just name)) + ExprEntry _ -> NewWork (toJavaScript info Nothing) + + +toJavaScript :: (Src.Module, Compile.Artifacts, Opt.GlobalGraph) -> Maybe N.Name -> B.Builder +toJavaScript (modul, Compile.Artifacts canModule types locals, objects) maybeName = + let + localizer = L.fromModule modul + graph = Opt.addLocalGraph locals objects + home = Can._name canModule + tipe = types ! maybe N.replValueToPrint id maybeName + in + JS.generateForReplEndpoint localizer graph home maybeName tipe + + +mapLeft :: (x -> y) -> Either x a -> Either y a +mapLeft func result = + either (Left . func) Right result + + +checkImports :: Map.Map ModuleName.Raw I.Interface -> [Src.Import] -> Either (NE.List Import.Error) (Map.Map ModuleName.Raw I.Interface) +checkImports interfaces imports = + let + importDict = Map.fromValues Src.getImportName imports + missing = Map.difference importDict interfaces + in + case Map.elems missing of + [] -> + Right (Map.intersection interfaces importDict) + + i:is -> + let + unimported = + Map.keysSet (Map.difference interfaces importDict) + + toError (Src.Import (A.At region name) _ _) = + Import.Error region name unimported Import.NotFound + in + Left (fmap toError (NE.List i is)) + + + +-- DECODE BODY + + +decodeBody :: LBS.ByteString -> Maybe ( Repl.State, String ) +decodeBody body = + case Aeson.eitherDecode body of + Right obj -> + Aeson.parseMaybe decodeBodyHelp obj + Left err -> + error $ show err + + +decodeBodyHelp :: Aeson.Object -> Aeson.Parser ( Repl.State, String ) +decodeBodyHelp obj = + let + get key = + do dict <- obj .: key + let f (k,v) = (N.fromChars k, B.stringUtf8 v) + return $ Map.fromList $ map f $ Map.toList dict + in + do imports <- get "imports" + types <- get "types" + decls <- get "decls" + entry <- obj .: "entry" + return ( Repl.State imports types decls, entry ) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json new file mode 100644 index 00000000..98f80d95 --- /dev/null +++ b/outlines/repl/elm.json @@ -0,0 +1,19 @@ +{ + "type": "application", + "source-directories": [ + "../../repl-src" + ], + "elm-version": "0.19.1", + "dependencies": { + "direct": { + "elm/core": "1.0.2" + }, + "indirect": { + "elm/json": "1.1.3" + } + }, + "test-dependencies": { + "direct": {}, + "indirect": {} + } +} \ No newline at end of file diff --git a/repl-src/.keep b/repl-src/.keep new file mode 100644 index 00000000..e69de29b diff --git a/terminal/src/Develop.hs b/terminal/src/Develop.hs index 71e3726b..ed9bdd32 100644 --- a/terminal/src/Develop.hs +++ b/terminal/src/Develop.hs @@ -23,6 +23,7 @@ import qualified Data.NonEmptyList as NE import qualified System.Directory as Dir import System.FilePath as FP import Snap.Core hiding (path) +import qualified Snap.Core as SnapCore import Snap.Http.Server import Snap.Util.FileServe @@ -54,6 +55,10 @@ import Control.Concurrent.STM (atomically, newTVarIO, readTVar, writeTVar, TVar) import StandaloneInstances +import qualified Artifacts +import qualified Endpoint.Repl as Repl + + -- RUN THE DEV SERVER @@ -120,6 +125,8 @@ runWithRoot root (Flags maybePort) = Lamdera.ReverseProxy.start + rArtifacts <- Artifacts.loadRepl + Live.withEnd liveState $ httpServe (config port) $ gcatchlog "general" $ -- Add /public/* as if it were /* to mirror production, but still render .elm files as an Elm app first @@ -130,6 +137,7 @@ runWithRoot root (Flags maybePort) = <|> route [ ("_r/:endpoint", Live.serveRpc liveState port) ] <|> Live.openEditorHandler root <|> Live.serveExperimental root + <|> (SnapCore.path "repl" $ Repl.endpoint rArtifacts) <|> serveAssets -- Compiler packaged static files <|> Live.serveUnmatchedUrlsToIndex root (serveElm sentryCache) -- Everything else without extensions goes to Lamdera LocalDev harness <|> error404 -- Will get hit for any non-matching extensioned paths i.e. /hello.blah diff --git a/test/Test.hs b/test/Test.hs index 6bb720b5..14a55ba5 100644 --- a/test/Test.hs +++ b/test/Test.hs @@ -125,12 +125,14 @@ previewProject = do --target = -- Test.Check.checkWithParams "/Users/mario/dev/projects/lamdera-dashboard" +-- target = +-- Test.Check.checkWithParams "/Users/mario/dev/projects/lamdera-dashboard" -- Test.Check.checkWithParams "/Users/mario/lamdera/test/sheep-game" "sheep-game" -- target = buildTestHarnessToProductionJs -- target = checkProjectCompiles -- target = previewProject --- target = liveReloadLive +target = liveReloadLive -- target = Test.Wire.all -- target = checkUserConfig -- target = Test.Wire.buildAllPackages From c097d3ec9285a1e89afa571399d90eabcbd6a414 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Sun, 17 Sep 2023 02:47:59 -0400 Subject: [PATCH 03/34] change alllowed origins to http://localhost:8007 only --- extra/Endpoint/Repl.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs index 84220846..6492ff60 100644 --- a/extra/Endpoint/Repl.hs +++ b/extra/Endpoint/Repl.hs @@ -48,7 +48,7 @@ import qualified Reporting.Render.Type.Localizer as L allowedOrigins :: [String] allowedOrigins = - [ "*" + [ "http://localhost:8007" ] From b2a2e5682618f101777308d2cb4c56ed46e54f86 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Sun, 17 Sep 2023 02:55:52 -0400 Subject: [PATCH 04/34] Exclude Jim's experimental files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index ec05c312..f064d6a0 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,6 @@ extra/.cache # @TESTS elm-home +# Jim +experimental/ +.vscode/ From e0d55f02ac5fd3415c0185546d931564765e8ca3 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 2 Oct 2023 09:04:21 -0400 Subject: [PATCH 05/34] Change Test.hs so as to talk to elm-notebook --- test/Test.hs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/Test.hs b/test/Test.hs index 14a55ba5..f03f0450 100644 --- a/test/Test.hs +++ b/test/Test.hs @@ -229,7 +229,9 @@ liveReloadLive = do -- let p = "/Users/mario/lamdera/test/v1" -- let p = "/Users/mario/dev/projects/bento-life" - let p = "/Users/mario/dev/projects/lamdera-dashboard" +-- let p = "/Users/mario/dev/projects/lamdera-dashboard" +-- let p = "/Users/carlson/dev/elm-notebook/elm-notebook-poc" + let p = "/Users/carlson/dev/elm-notebook/elm-notebook-v2" -- let p = "/Users/mario/dev/test/lamdera-init" -- let p = "/Users/mario/dev/test/nu-ashworld-lamdera" @@ -280,7 +282,7 @@ liveReloadLive = do -- "src/Bytes/Encode.elm" -- "withDebug" -target = EasyTest.run Test.WebGL.suite +--target = EasyTest.run Test.WebGL.suite all = EasyTest.run allTests From 7c8f3108a1c43a1411dd26d4eb28f283da74e734 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 2 Oct 2023 09:05:25 -0400 Subject: [PATCH 06/34] Add debug statements --- extra/Endpoint/Repl.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs index 6492ff60..7fdd9496 100644 --- a/extra/Endpoint/Repl.hs +++ b/extra/Endpoint/Repl.hs @@ -40,6 +40,8 @@ import qualified Reporting.Error.Import as Import import qualified Reporting.Exit as Exit import qualified Reporting.Exit.Help as Help import qualified Reporting.Render.Type.Localizer as L +import Lamdera as LA +import qualified Data.Text @@ -165,7 +167,7 @@ compile (A.Artifacts interfaces objects) state@(Repl.State imports types decls) ExprEntry src -> Repl.toByteString state (Repl.OutputExpr src) in case - do modul <- mapLeft Error.BadSyntax $ Parse.fromByteString Parse.Application source + do modul <- mapLeft Error.BadSyntax $ Parse.fromByteString Parse.Application (LA.debugPassText "SOURCE" ( Data.Text.pack $ show source) $ source) ifaces <- mapLeft Error.BadImports $ checkImports interfaces (Src._imports modul) artifacts <- Compile.compile Pkg.dummyName ifaces modul return ( modul, artifacts, objects ) From 8290dee117d9ad9d551a329d98b7831b52b9880c Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 2 Oct 2023 09:06:56 -0400 Subject: [PATCH 07/34] Added: '_ -> error $ "unreachable:" ++ show e' to function 'watch'. Is this needed? --- ext-sentry/Ext/Filewatch.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/ext-sentry/Ext/Filewatch.hs b/ext-sentry/Ext/Filewatch.hs index b2f29709..d696fc9b 100644 --- a/ext-sentry/Ext/Filewatch.hs +++ b/ext-sentry/Ext/Filewatch.hs @@ -37,6 +37,7 @@ watch root action = Modified f _ _ -> f Removed f _ _ -> f Unknown f _ _ _ -> f + _ -> error $ "unreachable:" ++ show e -- @TODO it would be better to not listen to these folders in the `watchTree` when available -- https://github.com/haskell-fswatch/hfsnotify/issues/101 From fa3cfe3a2f818681bde21edf044e58dc5224d46b Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 2 Oct 2023 09:07:49 -0400 Subject: [PATCH 08/34] I am committing this, but I can't see what has changed. --- .ghci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ghci b/.ghci index f44681c8..a974b592 100644 --- a/.ghci +++ b/.ghci @@ -1,4 +1,4 @@ :set -fbyte-code :set -fobject-code :set -fwarn-name-shadowing -:def rr const $ return $ unlines ["Ext.Common.killTrackedThreads",":r","Test.target"] +:def rr const $ return $ unlines ["Ext.Common.killTrackedThreads",":r","Test.target"] \ No newline at end of file From 441f1ce7a46ff594b6d6822ef306df3fac10bfe6 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 2 Oct 2023 19:41:06 -0400 Subject: [PATCH 09/34] Add elm-community/list-extra to outlines/repl/elm.json --- outlines/repl/elm.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 98f80d95..9053bf84 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -6,7 +6,8 @@ "elm-version": "0.19.1", "dependencies": { "direct": { - "elm/core": "1.0.2" + "elm/core": "1.0.2", + "elm-community/list-extra": "8.7.0" }, "indirect": { "elm/json": "1.1.3" From a27d4bbd99d7e0510f88f6efc97777d9b4bd1c39 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Wed, 4 Oct 2023 19:40:42 -0400 Subject: [PATCH 10/34] Remove duplicate elm.json entries --- outlines/repl/elm.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 9053bf84..463ec01c 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -10,7 +10,9 @@ "elm-community/list-extra": "8.7.0" }, "indirect": { - "elm/json": "1.1.3" + "elm/json": "1.1.3", + "elm/html": "1.0.0", + "elm/virtual-dom": "1.0.0" } }, "test-dependencies": { From d591f198ec84b045b5ec1d39909c8184d7683596 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Thu, 5 Oct 2023 05:47:12 -0400 Subject: [PATCH 11/34] Add module Endpoint.Package from extra/, (2) Chane Develop (in terminal) to call Endpoint.Package.handlePost: -- Client Elm app says that the package was accepted, but I find no change. --- extra/Endpoint/Package.hs | 64 +++++++++++++++++++++++++++++++++++++++ terminal/src/Develop.hs | 2 ++ 2 files changed, 66 insertions(+) create mode 100644 extra/Endpoint/Package.hs diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs new file mode 100644 index 00000000..b9b1d5b1 --- /dev/null +++ b/extra/Endpoint/Package.hs @@ -0,0 +1,64 @@ +{-# LANGUAGE OverloadedStrings #-} + +module Endpoint.Package (handlePost) where + +{-# LANGUAGE DeriveGeneric #-} + +import GHC.Generics (Generic) + + +import Snap.Core +import Snap.Http.Server +import Data.Aeson (FromJSON, eitherDecode, encode, ToJSON, toJSON, object, (.=)) +import Data.ByteString (ByteString) +import Data.ByteString.Lazy (toStrict) +import qualified Data.ByteString.Lazy.Char8 as BL +import qualified Data.ByteString.Char8 as ByteString +import GHC.Generics +import System.IO (writeFile) +import Control.Monad.IO.Class (liftIO) +import qualified Data.Map as Map + +import Snap.Http.Server.Config (setPort, defaultConfig) + +data Package = Package { name :: String, version :: String } deriving (Show, Generic) + +instance FromJSON Package +instance ToJSON Package + +type PackageList = [Package] + +writeElmJson :: PackageList -> IO () +writeElmJson pkgs = do + let directDeps = Map.fromList $ ("elm/core", "1.0.5"):[(name p, version p) | p <- pkgs] + elmJson = object [ + "type" .= ("application" :: String), + "source-directories" .= (["../../repl-src"] :: [String]), + "elm-version" .= ("0.19.1" :: String), + "dep endencies" .= object [ + "direct" .= directDeps, + "indirect" .= object [ + "elm/json" .= ("1.1.3" :: String) + ] + ], + "test-dependencies" .= object [ + "direct" .= (Map.empty :: Map.Map String String), + "indirect" .= (Map.empty :: Map.Map String String) + ] + ] + writeFile "../../outlines/repl/elm.json" ( BL.unpack $ encode elmJson) + + +handlePost :: Snap () +handlePost = do + body <- readRequestBody 10000 + let maybePackageList = eitherDecode body :: Either String PackageList + case maybePackageList of + Left err -> writeBS $ "Error: Could not decode JSON: " <> (ByteString.pack err) + Right packages -> do + liftIO $ writeElmJson packages + writeBS "Successfully received packages and wrote to elm.json" + +--routes :: [(ByteString, Snap ())] +--routes = [("/packageList", method POST handlePost)] + diff --git a/terminal/src/Develop.hs b/terminal/src/Develop.hs index ed9bdd32..b86bc9fe 100644 --- a/terminal/src/Develop.hs +++ b/terminal/src/Develop.hs @@ -57,6 +57,7 @@ import StandaloneInstances import qualified Artifacts import qualified Endpoint.Repl as Repl +import qualified Endpoint.Package as Package -- RUN THE DEV SERVER @@ -138,6 +139,7 @@ runWithRoot root (Flags maybePort) = <|> Live.openEditorHandler root <|> Live.serveExperimental root <|> (SnapCore.path "repl" $ Repl.endpoint rArtifacts) + <|> (SnapCore.path "packageList" $ Package.handlePost) <|> serveAssets -- Compiler packaged static files <|> Live.serveUnmatchedUrlsToIndex root (serveElm sentryCache) -- Everything else without extensions goes to Lamdera LocalDev harness <|> error404 -- Will get hit for any non-matching extensioned paths i.e. /hello.blah From d1d0cd9da98581a2e8c767fa8e5e1762084f71cf Mon Sep 17 00:00:00 2001 From: James Carlson Date: Thu, 5 Oct 2023 06:09:02 -0400 Subject: [PATCH 12/34] Fix path for writing the elm.json file --- extra/Endpoint/Package.hs | 2 +- outlines/repl/elm.json | 23 +---------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index b9b1d5b1..82ce8a4c 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -46,7 +46,7 @@ writeElmJson pkgs = do "indirect" .= (Map.empty :: Map.Map String String) ] ] - writeFile "../../outlines/repl/elm.json" ( BL.unpack $ encode elmJson) + writeFile "./outlines/repl/elm.json" ( BL.unpack $ encode elmJson) handlePost :: Snap () diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 463ec01c..295a5071 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1,22 +1 @@ -{ - "type": "application", - "source-directories": [ - "../../repl-src" - ], - "elm-version": "0.19.1", - "dependencies": { - "direct": { - "elm/core": "1.0.2", - "elm-community/list-extra": "8.7.0" - }, - "indirect": { - "elm/json": "1.1.3", - "elm/html": "1.0.0", - "elm/virtual-dom": "1.0.0" - } - }, - "test-dependencies": { - "direct": {}, - "indirect": {} - } -} \ No newline at end of file +{"dep endencies":{"direct":{"elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file From 92c1c803181ddde719226a057072fa2d4332440e Mon Sep 17 00:00:00 2001 From: James Carlson Date: Thu, 5 Oct 2023 09:36:41 -0400 Subject: [PATCH 13/34] Fix stray space in word "dependencies" --- extra/Endpoint/Package.hs | 5 ++--- outlines/repl/elm.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index 82ce8a4c..34245ed7 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -1,9 +1,8 @@ {-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE DeriveGeneric #-} module Endpoint.Package (handlePost) where -{-# LANGUAGE DeriveGeneric #-} - import GHC.Generics (Generic) @@ -35,7 +34,7 @@ writeElmJson pkgs = do "type" .= ("application" :: String), "source-directories" .= (["../../repl-src"] :: [String]), "elm-version" .= ("0.19.1" :: String), - "dep endencies" .= object [ + "dependencies" .= object [ "direct" .= directDeps, "indirect" .= object [ "elm/json" .= ("1.1.3" :: String) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 295a5071..bf7e4e29 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dep endencies":{"direct":{"elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} From 1e775beffd009949bda21e901ec730935edab41b Mon Sep 17 00:00:00 2001 From: James Carlson Date: Thu, 5 Oct 2023 10:41:08 -0400 Subject: [PATCH 14/34] Add type ElmPackage and decoder for it. --- outlines/repl/elm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index bf7e4e29..295a5071 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} +{"dep endencies":{"direct":{"elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file From 9e57721ce29ad6486de9a97b4742a1bd6739681a Mon Sep 17 00:00:00 2001 From: James Carlson Date: Thu, 5 Oct 2023 14:44:29 -0400 Subject: [PATCH 15/34] Return outlines/repl/elm.json to its original state --- outlines/repl/elm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 295a5071..e12348d4 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dep endencies":{"direct":{"elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm/core":"1.0.5", "elm-community/list-extra":"8.7.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file From c9af64d55d4ca752cc6b4d11eb81662c0dccf4e3 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Thu, 5 Oct 2023 16:51:21 -0400 Subject: [PATCH 16/34] Introduced a deterministic delay for executing Notebook.Package.nowSendPackageList: - Do this on receipt of the message ExecuteDelayedFunction - This is activated by delayCmd = Process.sleep delayInMs |> Task.perform (always Types.ExecuteDelayedFunction) in function Notebook.Package.updateElmJsonDependencies --- outlines/repl/elm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index e12348d4..ba997efa 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"elm/core":"1.0.5", "elm-community/list-extra":"8.7.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm-community/list-extra":"8.7.0","elm-community/maybe-extra":"5.3.0","elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file From 87727e68734f8c2bbcc55fc1bec03c91eb595a93 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Thu, 12 Oct 2023 19:11:12 -0400 Subject: [PATCH 17/34] When packages are added to elm.json, report to the client how many were added (in extra/Endpoint/Package.hs) --- extra/Endpoint/Package.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index 34245ed7..34de408b 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -56,8 +56,10 @@ handlePost = do Left err -> writeBS $ "Error: Could not decode JSON: " <> (ByteString.pack err) Right packages -> do liftIO $ writeElmJson packages - writeBS "Successfully received packages and wrote to elm.json" + let message = ByteString.pack $ "Packages added: " ++ (show $ length packages) + writeBS message +-- (show $ length packages) ++ --routes :: [(ByteString, Snap ())] --routes = [("/packageList", method POST handlePost)] From e544b92197daa62b50d644b81c217b9377ad9d93 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Fri, 13 Oct 2023 00:10:27 -0400 Subject: [PATCH 18/34] Draft 1 --- extra/Endpoint/Package.hs | 38 +++++++++++++++++++++++++++++++++----- outlines/repl/elm.json | 2 +- terminal/src/Develop.hs | 1 + 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index 34de408b..55e2cb01 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveGeneric #-} -module Endpoint.Package (handlePost) where +module Endpoint.Package (handlePost, reportOnInstalledPackages) where import GHC.Generics (Generic) @@ -17,7 +17,11 @@ import GHC.Generics import System.IO (writeFile) import Control.Monad.IO.Class (liftIO) import qualified Data.Map as Map - +--- +import Snap.Util.FileServe +import qualified Data.ByteString.Lazy as LBS +import qualified Data.HashMap.Strict as HM +import Data.Text.Encoding (decodeUtf8) import Snap.Http.Server.Config (setPort, defaultConfig) data Package = Package { name :: String, version :: String } deriving (Show, Generic) @@ -59,7 +63,31 @@ handlePost = do let message = ByteString.pack $ "Packages added: " ++ (show $ length packages) writeBS message --- (show $ length packages) ++ ---routes :: [(ByteString, Snap ())] ---routes = [("/packageList", method POST handlePost)] + +data Dependencies = Dependencies { + direct :: HM.HashMap String String + } deriving (Generic, Show) + +data TopLevel = TopLevel { + dependencies :: Dependencies + } deriving (Generic, Show) + +instance FromJSON TopLevel + +instance FromJSON Dependencies + +--- curl -X POST -H "Content-Length: 0" http://localhost:8000/reportOnInstalledPackages + +reportOnInstalledPackages :: Snap () +reportOnInstalledPackages = do + jsonData <- liftIO $ LBS.readFile "./outlines/repl/elm.json" + + + case eitherDecode jsonData :: Either String Dependencies of + Left err -> writeBS $ "Failed to parse JSON: " <> (LBS.toStrict jsonData) + Right deps -> do + let directDeps = HM.toList $ direct deps + -- Convert to your desired output format + outputList = map (\(name, version) -> "{\"name\": \"" ++ name ++ "\", \"version\": \"" ++ version ++ "\"}") directDeps + writeBS . LBS.toStrict . encode $ outputList \ No newline at end of file diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index ba997efa..26c3898d 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"elm-community/list-extra":"8.7.0","elm-community/maybe-extra":"5.3.0","elm/core":"1.0.5","elm/regex":"1.0.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm-community/list-extra":"8.7.0","elm-community/maybe-extra":"5.3.0","elm/core":"1.0.5","zwilias/elm-rosetree":"1.5.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file diff --git a/terminal/src/Develop.hs b/terminal/src/Develop.hs index b86bc9fe..d3e0ec26 100644 --- a/terminal/src/Develop.hs +++ b/terminal/src/Develop.hs @@ -140,6 +140,7 @@ runWithRoot root (Flags maybePort) = <|> Live.serveExperimental root <|> (SnapCore.path "repl" $ Repl.endpoint rArtifacts) <|> (SnapCore.path "packageList" $ Package.handlePost) + <|> (SnapCore.path "reportOnInstalledPackages" $ Package.reportOnInstalledPackages) <|> serveAssets -- Compiler packaged static files <|> Live.serveUnmatchedUrlsToIndex root (serveElm sentryCache) -- Everything else without extensions goes to Lamdera LocalDev harness <|> error404 -- Will get hit for any non-matching extensioned paths i.e. /hello.blah From 48def3ee4346728470817b9e82b7861b35d35b5a Mon Sep 17 00:00:00 2001 From: James Carlson Date: Fri, 13 Oct 2023 00:15:52 -0400 Subject: [PATCH 19/34] Draft 2 --- extra/Endpoint/Package.hs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index 55e2cb01..9ddf1c4c 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -82,12 +82,9 @@ instance FromJSON Dependencies reportOnInstalledPackages :: Snap () reportOnInstalledPackages = do jsonData <- liftIO $ LBS.readFile "./outlines/repl/elm.json" - - - case eitherDecode jsonData :: Either String Dependencies of + case eitherDecode jsonData :: Either String TopLevel of Left err -> writeBS $ "Failed to parse JSON: " <> (LBS.toStrict jsonData) - Right deps -> do - let directDeps = HM.toList $ direct deps - -- Convert to your desired output format + Right topLevel -> do + let directDeps = HM.toList $ direct $ dependencies topLevel outputList = map (\(name, version) -> "{\"name\": \"" ++ name ++ "\", \"version\": \"" ++ version ++ "\"}") directDeps writeBS . LBS.toStrict . encode $ outputList \ No newline at end of file From 3391d5f37723a052482f4be915618ba81c947987 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Fri, 13 Oct 2023 01:17:49 -0400 Subject: [PATCH 20/34] Fix JSON output --- extra/Endpoint/Package.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index 9ddf1c4c..c117a722 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -86,5 +86,5 @@ reportOnInstalledPackages = do Left err -> writeBS $ "Failed to parse JSON: " <> (LBS.toStrict jsonData) Right topLevel -> do let directDeps = HM.toList $ direct $ dependencies topLevel - outputList = map (\(name, version) -> "{\"name\": \"" ++ name ++ "\", \"version\": \"" ++ version ++ "\"}") directDeps - writeBS . LBS.toStrict . encode $ outputList \ No newline at end of file + let outputList = map (\(name, version) -> object ["name" .= name, "version" .= version]) directDeps + writeBS . LBS.toStrict . encode $ outputList From b72710188fef07fc83ce6365a057de42462885a1 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Fri, 13 Oct 2023 20:15:44 -0400 Subject: [PATCH 21/34] Implement dynamic loading of packages submitted to the Elm compiler. --- extra/Endpoint/Package.hs | 10 ++++++++-- extra/Endpoint/Repl.hs | 10 ++++++---- outlines/repl/elm.json | 2 +- terminal/src/Develop.hs | 14 +++++++++++--- 4 files changed, 26 insertions(+), 10 deletions(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index c117a722..dcf87adb 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -23,12 +23,16 @@ import qualified Data.ByteString.Lazy as LBS import qualified Data.HashMap.Strict as HM import Data.Text.Encoding (decodeUtf8) import Snap.Http.Server.Config (setPort, defaultConfig) +import qualified Artifacts +import Data.IORef + data Package = Package { name :: String, version :: String } deriving (Show, Generic) instance FromJSON Package instance ToJSON Package + type PackageList = [Package] writeElmJson :: PackageList -> IO () @@ -52,8 +56,8 @@ writeElmJson pkgs = do writeFile "./outlines/repl/elm.json" ( BL.unpack $ encode elmJson) -handlePost :: Snap () -handlePost = do +handlePost :: IORef Artifacts.Artifacts -> Snap () +handlePost artifactRef = do body <- readRequestBody 10000 let maybePackageList = eitherDecode body :: Either String PackageList case maybePackageList of @@ -62,6 +66,8 @@ handlePost = do liftIO $ writeElmJson packages let message = ByteString.pack $ "Packages added: " ++ (show $ length packages) writeBS message + newArtifacts <- liftIO Artifacts.loadRepl + liftIO $ writeIORef artifactRef newArtifacts diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs index 7fdd9496..c757b897 100644 --- a/extra/Endpoint/Repl.hs +++ b/extra/Endpoint/Repl.hs @@ -43,6 +43,7 @@ import qualified Reporting.Render.Type.Localizer as L import Lamdera as LA import qualified Data.Text +import Data.IORef -- ALLOWED ORIGINS @@ -58,13 +59,14 @@ allowedOrigins = -- ENDPOINT -endpoint :: A.Artifacts -> Snap () -endpoint artifacts = +endpoint :: IORef A.Artifacts -> Snap () +endpoint artifactRef = Cors.allow POST allowedOrigins $ - do body <- readRequestBody (64 * 1024) + do currentArtifacts <- liftIO $ readIORef artifactRef + body <- readRequestBody (64 * 1024) case decodeBody body of Just (state, entry) -> - serveOutcome (toOutcome artifacts state entry) + serveOutcome (toOutcome currentArtifacts state entry) Nothing -> do modifyResponse $ setResponseStatus 400 "Bad Request" diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 26c3898d..59b82f99 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"elm-community/list-extra":"8.7.0","elm-community/maybe-extra":"5.3.0","elm/core":"1.0.5","zwilias/elm-rosetree":"1.5.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"Chadtech/elm-bool-extra":"2.4.2","elm-community/list-extra":"8.7.0","elm-community/maybe-extra":"5.3.0","elm/core":"1.0.5"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file diff --git a/terminal/src/Develop.hs b/terminal/src/Develop.hs index d3e0ec26..42da9a9c 100644 --- a/terminal/src/Develop.hs +++ b/terminal/src/Develop.hs @@ -59,6 +59,7 @@ import qualified Artifacts import qualified Endpoint.Repl as Repl import qualified Endpoint.Package as Package +import Data.IORef -- RUN THE DEV SERVER @@ -74,6 +75,7 @@ run () flags = do root <- getProjectRoot "Develop.run" runWithRoot root flags +-- currentArtifacts <- liftIO $ readIORef artifactRef runWithRoot :: FilePath -> Flags -> IO () runWithRoot root (Flags maybePort) = @@ -92,6 +94,10 @@ runWithRoot root (Flags maybePort) = sentryCache <- liftIO $ Sentry.init + initialArtifacts <- Artifacts.loadRepl + artifactRef <- newIORef initialArtifacts + + let recompile :: [String] -> IO () recompile events = do @@ -126,7 +132,9 @@ runWithRoot root (Flags maybePort) = Lamdera.ReverseProxy.start - rArtifacts <- Artifacts.loadRepl + -- rArtifacts <- Artifacts.loadRepl + initialArtifacts <- Artifacts.loadRepl + artifactRef <- newIORef initialArtifacts Live.withEnd liveState $ httpServe (config port) $ gcatchlog "general" $ @@ -138,8 +146,8 @@ runWithRoot root (Flags maybePort) = <|> route [ ("_r/:endpoint", Live.serveRpc liveState port) ] <|> Live.openEditorHandler root <|> Live.serveExperimental root - <|> (SnapCore.path "repl" $ Repl.endpoint rArtifacts) - <|> (SnapCore.path "packageList" $ Package.handlePost) + <|> (SnapCore.path "repl" $ Repl.endpoint artifactRef) + <|> (SnapCore.path "packageList" $ Package.handlePost artifactRef) <|> (SnapCore.path "reportOnInstalledPackages" $ Package.reportOnInstalledPackages) <|> serveAssets -- Compiler packaged static files <|> Live.serveUnmatchedUrlsToIndex root (serveElm sentryCache) -- Everything else without extensions goes to Lamdera LocalDev harness From 8046918a8bf893a7a0ebcfc9877ddc1999dcc14e Mon Sep 17 00:00:00 2001 From: James Carlson Date: Fri, 13 Oct 2023 20:16:46 -0400 Subject: [PATCH 22/34] Return outlines/repl/elm.json to its original state --- outlines/repl/elm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 59b82f99..ee6cf8f6 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"Chadtech/elm-bool-extra":"2.4.2","elm-community/list-extra":"8.7.0","elm-community/maybe-extra":"5.3.0","elm/core":"1.0.5"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm/core":"1.0.5"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file From 3935f9df0a7535cab86ad319288350fe640afc4d Mon Sep 17 00:00:00 2001 From: James Carlson Date: Sun, 15 Oct 2023 12:02:22 -0400 Subject: [PATCH 23/34] fix but in properly computng evalstate before compilation. --- worker/src/Endpoint/Compile.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/worker/src/Endpoint/Compile.hs b/worker/src/Endpoint/Compile.hs index f3d0d246..26f3991e 100644 --- a/worker/src/Endpoint/Compile.hs +++ b/worker/src/Endpoint/Compile.hs @@ -59,6 +59,7 @@ allowedOrigins :: [String] allowedOrigins = [ "https://elm-lang.org" , "https://package.elm-lang.org" + ,"http://localhost:8007" ] From effbe4000ae870cbc9b6629506d01c68e779f665 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 06:57:32 -0400 Subject: [PATCH 24/34] Add debug code to Endpoint/Repl.hs --- extra/Endpoint/Repl.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs index c757b897..481303b3 100644 --- a/extra/Endpoint/Repl.hs +++ b/extra/Endpoint/Repl.hs @@ -169,7 +169,7 @@ compile (A.Artifacts interfaces objects) state@(Repl.State imports types decls) ExprEntry src -> Repl.toByteString state (Repl.OutputExpr src) in case - do modul <- mapLeft Error.BadSyntax $ Parse.fromByteString Parse.Application (LA.debugPassText "SOURCE" ( Data.Text.pack $ show source) $ source) + do modul <- mapLeft Error.BadSyntax $ Parse.fromByteString Parse.Application (LA.debugPassText "@SOURCE" ( Data.Text.pack $ show source) $ source) ifaces <- mapLeft Error.BadImports $ checkImports interfaces (Src._imports modul) artifacts <- Compile.compile Pkg.dummyName ifaces modul return ( modul, artifacts, objects ) From 8a8a9949103c6803fcfe75772b18e71f197fadf9 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 07:02:04 -0400 Subject: [PATCH 25/34] Add 'compiler.iml' to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f064d6a0..ee3504e8 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ elm-home # Jim experimental/ .vscode/ +compiler.iml From bdf9ffcf13cb88f91d7dd256f7212b7df86de309 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 09:06:10 -0400 Subject: [PATCH 26/34] Return to previous working state --- extra/Artifacts.hs | 155 ----------------------------------------- outlines/repl/elm.json | 2 +- 2 files changed, 1 insertion(+), 156 deletions(-) delete mode 100644 extra/Artifacts.hs diff --git a/extra/Artifacts.hs b/extra/Artifacts.hs deleted file mode 100644 index 0a03f52a..00000000 --- a/extra/Artifacts.hs +++ /dev/null @@ -1,155 +0,0 @@ -{-# OPTIONS_GHC -Wall #-} -module Artifacts - ( Artifacts(..) - , loadCompile - , loadRepl - , toDepsInfo - ) - where - - -import Control.Concurrent (readMVar) -import Control.Monad (liftM2) -import qualified Data.ByteString as BS -import qualified Data.ByteString.Builder as B -import qualified Data.ByteString.Lazy as LBS -import qualified Data.Map as Map -import qualified Data.Name as N -import qualified Data.OneOrMore as OneOrMore -import qualified System.Directory as Dir -import System.FilePath (()) - -import qualified AST.Canonical as Can -import qualified AST.Optimized as Opt -import qualified BackgroundWriter as BW -import qualified Elm.Details as Details -import qualified Elm.Interface as I -import qualified Elm.ModuleName as ModuleName -import qualified Elm.Package as Pkg -import Json.Encode ((==>)) -import qualified Json.Encode as E -import qualified Json.String as Json -import qualified Reporting - - - --- ARTIFACTS - - -data Artifacts = - Artifacts - { _ifaces :: Map.Map ModuleName.Raw I.Interface - , _graph :: Opt.GlobalGraph - } - - -loadCompile :: IO Artifacts -loadCompile = - load ("outlines" "compile") - - -loadRepl :: IO Artifacts -loadRepl = - load ("outlines" "repl") - - - --- LOAD - - -load :: FilePath -> IO Artifacts -load dir = - BW.withScope $ \scope -> - do putStrLn $ "Loading " ++ dir "elm.json" - style <- Reporting.terminal - root <- fmap ( dir) Dir.getCurrentDirectory - result <- Details.load style scope root - case result of - Left _ -> - error $ "Ran into some problem loading elm.json\nTry running `lamdera make` in: " ++ dir - - Right details -> - do omvar <- Details.loadObjects root details - imvar <- Details.loadInterfaces root details - mdeps <- readMVar imvar - mobjs <- readMVar omvar - case liftM2 (,) mdeps mobjs of - Nothing -> - error $ "Ran into some weird problem loading elm.json\nTry running `lamdera make` in: " ++ dir - - Just (deps, objs) -> - return $ Artifacts (toInterfaces deps) objs - - -toInterfaces :: Map.Map ModuleName.Canonical I.DependencyInterface -> Map.Map ModuleName.Raw I.Interface -toInterfaces deps = - Map.mapMaybe toUnique $ Map.fromListWith OneOrMore.more $ - Map.elems (Map.mapMaybeWithKey getPublic deps) - - -getPublic :: ModuleName.Canonical -> I.DependencyInterface -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore I.Interface) -getPublic (ModuleName.Canonical _ name) dep = - case dep of - I.Public iface -> Just (name, OneOrMore.one iface) - I.Private _ _ _ -> Nothing - - -toUnique :: OneOrMore.OneOrMore a -> Maybe a -toUnique oneOrMore = - case oneOrMore of - OneOrMore.One value -> Just value - OneOrMore.More _ _ -> Nothing - - - --- TO DEPS INFO - - -toDepsInfo :: Artifacts -> BS.ByteString -toDepsInfo (Artifacts ifaces _) = - LBS.toStrict $ B.toLazyByteString $ E.encodeUgly $ encode ifaces - - - --- ENCODE - - -encode :: Map.Map ModuleName.Raw I.Interface -> E.Value -encode ifaces = - E.dict Json.fromName encodeInterface ifaces - - -encodeInterface :: I.Interface -> E.Value -encodeInterface (I.Interface pkg values unions aliases binops) = - E.object - [ "pkg" ==> E.chars (Pkg.toChars pkg) - , "ops" ==> E.list E.name (Map.keys binops) - , "values" ==> E.list E.name (Map.keys values) - , "aliases" ==> E.list E.name (Map.keys (Map.filter isPublicAlias aliases)) - , "types" ==> E.dict Json.fromName (E.list E.name) (Map.mapMaybe toPublicUnion unions) - ] - - -isPublicAlias :: I.Alias -> Bool -isPublicAlias alias = - case alias of - I.PublicAlias _ -> True - I.PrivateAlias _ -> False - - -toPublicUnion :: I.Union -> Maybe [N.Name] -toPublicUnion union = - case union of - I.OpenUnion (Can.Union _ variants _ _) -> - Just (map getVariantName variants) - - I.ClosedUnion _ -> - Just [] - - I.PrivateUnion _ -> - Nothing - - -getVariantName :: Can.Ctor -> N.Name -getVariantName (Can.Ctor name _ _ _) = - name diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index ee6cf8f6..9c6dbc40 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"elm/core":"1.0.5"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm/core":"1.0.5","elm/parser":"1.1.0","elm/random":"1.0.0","zwilias/elm-rosetree":"1.5.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file From 7d4f07887b72a321db8e2bc453c02860699cd917 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 09:06:50 -0400 Subject: [PATCH 27/34] add back extra/Artifacts.hs --- extra/Artifacts.hs | 155 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 extra/Artifacts.hs diff --git a/extra/Artifacts.hs b/extra/Artifacts.hs new file mode 100644 index 00000000..0a03f52a --- /dev/null +++ b/extra/Artifacts.hs @@ -0,0 +1,155 @@ +{-# OPTIONS_GHC -Wall #-} +module Artifacts + ( Artifacts(..) + , loadCompile + , loadRepl + , toDepsInfo + ) + where + + +import Control.Concurrent (readMVar) +import Control.Monad (liftM2) +import qualified Data.ByteString as BS +import qualified Data.ByteString.Builder as B +import qualified Data.ByteString.Lazy as LBS +import qualified Data.Map as Map +import qualified Data.Name as N +import qualified Data.OneOrMore as OneOrMore +import qualified System.Directory as Dir +import System.FilePath (()) + +import qualified AST.Canonical as Can +import qualified AST.Optimized as Opt +import qualified BackgroundWriter as BW +import qualified Elm.Details as Details +import qualified Elm.Interface as I +import qualified Elm.ModuleName as ModuleName +import qualified Elm.Package as Pkg +import Json.Encode ((==>)) +import qualified Json.Encode as E +import qualified Json.String as Json +import qualified Reporting + + + +-- ARTIFACTS + + +data Artifacts = + Artifacts + { _ifaces :: Map.Map ModuleName.Raw I.Interface + , _graph :: Opt.GlobalGraph + } + + +loadCompile :: IO Artifacts +loadCompile = + load ("outlines" "compile") + + +loadRepl :: IO Artifacts +loadRepl = + load ("outlines" "repl") + + + +-- LOAD + + +load :: FilePath -> IO Artifacts +load dir = + BW.withScope $ \scope -> + do putStrLn $ "Loading " ++ dir "elm.json" + style <- Reporting.terminal + root <- fmap ( dir) Dir.getCurrentDirectory + result <- Details.load style scope root + case result of + Left _ -> + error $ "Ran into some problem loading elm.json\nTry running `lamdera make` in: " ++ dir + + Right details -> + do omvar <- Details.loadObjects root details + imvar <- Details.loadInterfaces root details + mdeps <- readMVar imvar + mobjs <- readMVar omvar + case liftM2 (,) mdeps mobjs of + Nothing -> + error $ "Ran into some weird problem loading elm.json\nTry running `lamdera make` in: " ++ dir + + Just (deps, objs) -> + return $ Artifacts (toInterfaces deps) objs + + +toInterfaces :: Map.Map ModuleName.Canonical I.DependencyInterface -> Map.Map ModuleName.Raw I.Interface +toInterfaces deps = + Map.mapMaybe toUnique $ Map.fromListWith OneOrMore.more $ + Map.elems (Map.mapMaybeWithKey getPublic deps) + + +getPublic :: ModuleName.Canonical -> I.DependencyInterface -> Maybe (ModuleName.Raw, OneOrMore.OneOrMore I.Interface) +getPublic (ModuleName.Canonical _ name) dep = + case dep of + I.Public iface -> Just (name, OneOrMore.one iface) + I.Private _ _ _ -> Nothing + + +toUnique :: OneOrMore.OneOrMore a -> Maybe a +toUnique oneOrMore = + case oneOrMore of + OneOrMore.One value -> Just value + OneOrMore.More _ _ -> Nothing + + + +-- TO DEPS INFO + + +toDepsInfo :: Artifacts -> BS.ByteString +toDepsInfo (Artifacts ifaces _) = + LBS.toStrict $ B.toLazyByteString $ E.encodeUgly $ encode ifaces + + + +-- ENCODE + + +encode :: Map.Map ModuleName.Raw I.Interface -> E.Value +encode ifaces = + E.dict Json.fromName encodeInterface ifaces + + +encodeInterface :: I.Interface -> E.Value +encodeInterface (I.Interface pkg values unions aliases binops) = + E.object + [ "pkg" ==> E.chars (Pkg.toChars pkg) + , "ops" ==> E.list E.name (Map.keys binops) + , "values" ==> E.list E.name (Map.keys values) + , "aliases" ==> E.list E.name (Map.keys (Map.filter isPublicAlias aliases)) + , "types" ==> E.dict Json.fromName (E.list E.name) (Map.mapMaybe toPublicUnion unions) + ] + + +isPublicAlias :: I.Alias -> Bool +isPublicAlias alias = + case alias of + I.PublicAlias _ -> True + I.PrivateAlias _ -> False + + +toPublicUnion :: I.Union -> Maybe [N.Name] +toPublicUnion union = + case union of + I.OpenUnion (Can.Union _ variants _ _) -> + Just (map getVariantName variants) + + I.ClosedUnion _ -> + Just [] + + I.PrivateUnion _ -> + Nothing + + +getVariantName :: Can.Ctor -> N.Name +getVariantName (Can.Ctor name _ _ _) = + name From be46c867bf5efe7044c8a1619ded4c2de1382242 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 09:12:59 -0400 Subject: [PATCH 28/34] Restore elm.json to original state --- outlines/repl/elm.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index 9c6dbc40..ee6cf8f6 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"elm/core":"1.0.5","elm/parser":"1.1.0","elm/random":"1.0.0","zwilias/elm-rosetree":"1.5.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm/core":"1.0.5"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file From ac87fe890f8acad3295428e52d97a04a72a2503f Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 09:26:21 -0400 Subject: [PATCH 29/34] Renamed: extra/Artifacts.hs -> extra/ReplArtifacts.hs --- extra/Endpoint/Package.hs | 6 +++--- extra/Endpoint/Repl.hs | 2 +- extra/{Artifacts.hs => ReplArtifacts.hs} | 2 +- terminal/src/Develop.hs | 8 ++++---- worker/elm.cabal | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) rename extra/{Artifacts.hs => ReplArtifacts.hs} (99%) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index dcf87adb..f5d017f9 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -23,7 +23,7 @@ import qualified Data.ByteString.Lazy as LBS import qualified Data.HashMap.Strict as HM import Data.Text.Encoding (decodeUtf8) import Snap.Http.Server.Config (setPort, defaultConfig) -import qualified Artifacts +import qualified ReplArtifacts import Data.IORef @@ -56,7 +56,7 @@ writeElmJson pkgs = do writeFile "./outlines/repl/elm.json" ( BL.unpack $ encode elmJson) -handlePost :: IORef Artifacts.Artifacts -> Snap () +handlePost :: IORef ReplArtifacts.Artifacts -> Snap () handlePost artifactRef = do body <- readRequestBody 10000 let maybePackageList = eitherDecode body :: Either String PackageList @@ -66,7 +66,7 @@ handlePost artifactRef = do liftIO $ writeElmJson packages let message = ByteString.pack $ "Packages added: " ++ (show $ length packages) writeBS message - newArtifacts <- liftIO Artifacts.loadRepl + newArtifacts <- liftIO ReplArtifacts.loadRepl liftIO $ writeIORef artifactRef newArtifacts diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs index 481303b3..6660e08e 100644 --- a/extra/Endpoint/Repl.hs +++ b/extra/Endpoint/Repl.hs @@ -19,7 +19,7 @@ import qualified Data.Name as N import qualified Data.NonEmptyList as NE import Snap.Core -import qualified Artifacts as A +import qualified ReplArtifacts as A import qualified Cors import qualified AST.Source as Src diff --git a/extra/Artifacts.hs b/extra/ReplArtifacts.hs similarity index 99% rename from extra/Artifacts.hs rename to extra/ReplArtifacts.hs index 0a03f52a..6fa44fb5 100644 --- a/extra/Artifacts.hs +++ b/extra/ReplArtifacts.hs @@ -1,5 +1,5 @@ {-# OPTIONS_GHC -Wall #-} -module Artifacts +module ReplArtifacts ( Artifacts(..) , loadCompile , loadRepl diff --git a/terminal/src/Develop.hs b/terminal/src/Develop.hs index 42da9a9c..0061b6a5 100644 --- a/terminal/src/Develop.hs +++ b/terminal/src/Develop.hs @@ -55,7 +55,7 @@ import Control.Concurrent.STM (atomically, newTVarIO, readTVar, writeTVar, TVar) import StandaloneInstances -import qualified Artifacts +import qualified ReplArtifacts import qualified Endpoint.Repl as Repl import qualified Endpoint.Package as Package @@ -94,7 +94,7 @@ runWithRoot root (Flags maybePort) = sentryCache <- liftIO $ Sentry.init - initialArtifacts <- Artifacts.loadRepl + initialArtifacts <- ReplArtifacts.loadRepl artifactRef <- newIORef initialArtifacts @@ -132,8 +132,8 @@ runWithRoot root (Flags maybePort) = Lamdera.ReverseProxy.start - -- rArtifacts <- Artifacts.loadRepl - initialArtifacts <- Artifacts.loadRepl + -- rArtifacts <- ReplArtifacts.loadRepl + initialArtifacts <- ReplArtifacts.loadRepl artifactRef <- newIORef initialArtifacts Live.withEnd liveState $ diff --git a/worker/elm.cabal b/worker/elm.cabal index be929489..795cb9d7 100644 --- a/worker/elm.cabal +++ b/worker/elm.cabal @@ -49,7 +49,7 @@ Executable worker Main.hs other-modules: - Artifacts + ReplArtifacts Cors Endpoint.Compile Endpoint.Donate From dc1fbe5bc8b6b7909fe128309e358147d66ac5ec Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 10:25:38 -0400 Subject: [PATCH 30/34] Add comment explaining the purpose of module Package --- extra/Endpoint/Package.hs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index f5d017f9..aa0c17a1 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -3,9 +3,32 @@ module Endpoint.Package (handlePost, reportOnInstalledPackages) where -import GHC.Generics (Generic) +{- + 1. + + This endpoint will respond to POST requests to "https://repl.lamdera.com/packageList" + with a JSON body of the form: + [ + { "name": "elm/core", "version": "1.0.5" }, + { "name": "elm/html", "version": "1.0.0" } + ] + It will write an elm.json file to the repl directory, and then reload the repl. + This response is mediate by function `handlePost` below. + + 2. + + In additon, this endpoint will respond to GET requests to "https://repl.lamdera.com/reportOnInstalledPackages" + with a JSON body of the form: + [ + { "name": "elm/core", "version": "1.0.5" }, + { "name": "elm/html", "version": "1.0.0" } + ] + The json body reports on the packages that are currently installed in the repl. + This response is mediated by function `reportOnInstalledPackages` below. +-} +import GHC.Generics (Generic) import Snap.Core import Snap.Http.Server import Data.Aeson (FromJSON, eitherDecode, encode, ToJSON, toJSON, object, (.=)) From b4229511e5aa632a9672795dc7e04e41b94f6347 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 11:08:18 -0400 Subject: [PATCH 31/34] Add comments to explain the purpose and operation of extra/Endpoint/Package.sh and extrra/EndPoin --- extra/Endpoint/Package.hs | 7 +++++++ extra/Endpoint/Repl.hs | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/extra/Endpoint/Package.hs b/extra/Endpoint/Package.hs index aa0c17a1..6526d6a4 100644 --- a/extra/Endpoint/Package.hs +++ b/extra/Endpoint/Package.hs @@ -25,6 +25,13 @@ module Endpoint.Package (handlePost, reportOnInstalledPackages) where ] The json body reports on the packages that are currently installed in the repl. This response is mediated by function `reportOnInstalledPackages` below. + + NOTE. handlePost and reportOnInstalledPackages + are referenced in the Snap webserver at Develop.runWithRoot + via the code fragments + + SnapCore.path "packageList" $ Package.handlePost artifactRef) + SnapCore.path "reportOnInstalledPackages" $ Package.reportOnInstalledPackages) -} diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs index 6660e08e..db6f0766 100644 --- a/extra/Endpoint/Repl.hs +++ b/extra/Endpoint/Repl.hs @@ -5,6 +5,42 @@ module Endpoint.Repl ) where +{- + The purpose of this endpoint is to provide a REPL for Elm that + is accessible via Http requests. The function `endpoint` of + this module is referenced in the Snap webserver at Develop.runWithRoot + via the code fragment + + SnapCore.path "repl" $ Repl.endpoint artifactRef + + + Function decodeBodyHelp decodes incoming Json requests to the repl. + The Json data has the form + + { "imports": , + "types": , + "decls": , + "entry": + } + + where the dictionaries are of the form + + { "name": , "source": } + + and "entry" the string representation of the Elm + code to be evaluated. + + Here is a typical incoming json object from a request to + evaluate `run (first int (symbol ".")) "42."`: + + entry: "run (first int (symbol \".\")) \"42.\"" + imports: Dict.fromList [("Parser","import Parser exposing(..)\n")] + decls: Dict.fromList [("first p q","first p q = p |> andThen (\s -> q |> map (\_ -> s))\n"))] + types: Dict.fromList [] + + + +-} import Data.Aeson ((.:)) import qualified Data.Aeson as Aeson @@ -18,10 +54,8 @@ import qualified Data.Map.Utils as Map import qualified Data.Name as N import qualified Data.NonEmptyList as NE import Snap.Core - import qualified ReplArtifacts as A import qualified Cors - import qualified AST.Source as Src import qualified AST.Canonical as Can import qualified AST.Optimized as Opt From 14b46e636b2a0aad8d5223be5eaf4e734d8d321e Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 12:51:05 -0400 Subject: [PATCH 32/34] More comments --- extra/Endpoint/Repl.hs | 20 ++++++++++++++++++++ terminal/src/Develop.hs | 1 - 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/extra/Endpoint/Repl.hs b/extra/Endpoint/Repl.hs index db6f0766..d721dfe4 100644 --- a/extra/Endpoint/Repl.hs +++ b/extra/Endpoint/Repl.hs @@ -38,7 +38,27 @@ module Endpoint.Repl decls: Dict.fromList [("first p q","first p q = p |> andThen (\s -> q |> map (\_ -> s))\n"))] types: Dict.fromList [] + NOTES. + 1. Repl.endpoint defined here is called by the Snap server Develop.runWithRoot + via the code fragment + + SnapCore.path "repl" $ Repl.endpoint artifactRef + + 2. The value of of artifactRef is set by + + initialArtifacts <- ReplArtifacts.loadRepl + + in `Develop.runWithRoot`. + + 3. If `endpoint artifactRef` successfully decodes the request, it + passes the resulting information to + + toOutcome :: A.Artifacts -> Repl.State -> String -> Outcome + + which in turn passes the information to `compile`. The result + of compilation is handed to `serveOutcome` which (at long last) + replies to the client's request. -} diff --git a/terminal/src/Develop.hs b/terminal/src/Develop.hs index 0061b6a5..fa4dbe45 100644 --- a/terminal/src/Develop.hs +++ b/terminal/src/Develop.hs @@ -132,7 +132,6 @@ runWithRoot root (Flags maybePort) = Lamdera.ReverseProxy.start - -- rArtifacts <- ReplArtifacts.loadRepl initialArtifacts <- ReplArtifacts.loadRepl artifactRef <- newIORef initialArtifacts From 20bb71e24d5cc84a7004d62a00e503c10d04484a Mon Sep 17 00:00:00 2001 From: James Carlson Date: Mon, 30 Oct 2023 12:54:06 -0400 Subject: [PATCH 33/34] Comments for ReplArtifacts --- extra/ReplArtifacts.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/extra/ReplArtifacts.hs b/extra/ReplArtifacts.hs index 6fa44fb5..2852853a 100644 --- a/extra/ReplArtifacts.hs +++ b/extra/ReplArtifacts.hs @@ -7,6 +7,12 @@ module ReplArtifacts ) where +{- + + load artifacts for /extra/Endpoint/Repl. See note (2) in that file. + +-} + import Control.Concurrent (readMVar) import Control.Monad (liftM2) From 91736333d72182ab6374d09e85e4fc418fb02177 Mon Sep 17 00:00:00 2001 From: James Carlson Date: Wed, 17 Jan 2024 17:43:38 -0500 Subject: [PATCH 34/34] Add clause 'Types.OnConnected sessionId clientId' to Backend.update: - use to wire in Backend.Session.reconnect and Backend.Session.sendUserData --- outlines/repl/elm.json | 2 +- test/Test.hs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/outlines/repl/elm.json b/outlines/repl/elm.json index ee6cf8f6..1b34e293 100644 --- a/outlines/repl/elm.json +++ b/outlines/repl/elm.json @@ -1 +1 @@ -{"dependencies":{"direct":{"elm/core":"1.0.5"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file +{"dependencies":{"direct":{"elm/core":"1.0.5","zwilias/elm-rosetree":"1.5.0"},"indirect":{"elm/json":"1.1.3"}},"elm-version":"0.19.1","source-directories":["../../repl-src"],"test-dependencies":{"direct":{},"indirect":{}},"type":"application"} \ No newline at end of file diff --git a/test/Test.hs b/test/Test.hs index f03f0450..86411148 100644 --- a/test/Test.hs +++ b/test/Test.hs @@ -229,9 +229,9 @@ liveReloadLive = do -- let p = "/Users/mario/lamdera/test/v1" -- let p = "/Users/mario/dev/projects/bento-life" --- let p = "/Users/mario/dev/projects/lamdera-dashboard" --- let p = "/Users/carlson/dev/elm-notebook/elm-notebook-poc" - let p = "/Users/carlson/dev/elm-notebook/elm-notebook-v2" + -- let p = "/Users/mario/dev/projects/lamdera-dashboard" + -- let p = "/Users/carlson/dev/elm-notebook/elm-notebook-poc" + let p = "/Users/carlson/dev/elm-work/notebook/elm-notebook-v2" -- let p = "/Users/mario/dev/test/lamdera-init" -- let p = "/Users/mario/dev/test/nu-ashworld-lamdera"