@@ -10,7 +10,7 @@ import Data.Aeson
1010import Data.Aeson.Types
1111import Data.Char
1212import Data.FileEmbed (embedFile)
13−import Data.List (delete, intercalate, isPrefixOf, nub, partition)
13+import Data.List (delete, intercalate, isPrefixOf, nub, partition, (\\))
1414import Data.Maybe
1515import Data.Monoid ((<>))
1616import Data.Version
@@ -20,7 +20,7 @@ import Text.Printf
2020
2121import System.Environment
2222import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getCurrentDirectory, getModificationTime)
23−import System.FilePath ((</>), joinPath, searchPathSeparator, splitDirectories, takeDirectory)
23+import System.FilePath ((</>), joinPath, splitDirectories, takeDirectory)
2424import System.FilePath.Find
2525import System.Process
2626
@@ -100,11 +100,11 @@ main = do
100100 basePath :: [FilePath] -> FilePath
101101 basePath files =
102102 let filepath = takeDirectory (head files) in
103− joinPath $ (init $ splitDirectories filepath) ++ [outdir]
103+ joinPath $ (init $ splitDirectories filepath)
104104 generateFiles :: [String] -> [FilePath] -> IO ()
105105 generateFiles opts files = do
106106 let baseOutpath = basePath files
107− writeRuntimeFiles baseOutpath
107+ writeSupportFiles baseOutpath
108108 Par.mapM (generateCode opts baseOutpath) files
109109 return ()
110110 runBuildTool :: Command -> IO ()
@@ -112,33 +112,19 @@ main = do
112112 let command = case cmd of
113113 Build -> "build"
114114 Run -> "run"
115− currentDir <- getCurrentDirectory
116− files <- find always (extension ==? goSrc) currentDir
117− let fileDirs = nub $ joinPath . init <$> filter isSrc (getDir <$> files)
118− currentEnv <- getEnvironment
119− let pathDirs = maybe id (:) (lookup "GOPATH" currentEnv) $ fileDirs
120− searchPath = intercalate [searchPathSeparator] pathDirs
121− env = ("GOPATH", searchPath) : currentEnv
122− (_, _, _, p) <- createProcess (proc "go" [command, "Main"]){ env = Just env }
115+ (_, _, _, p) <- createProcess (proc "go" [command, T.unpack modPrefix <> "/Main"])
123116 waitForProcess p
124117 return ()
125− where
126− getDir :: FilePath -> [FilePath]
127− getDir file =
128− let filepath = takeDirectory file in
129− init $ splitDirectories filepath
130− isSrc :: [FilePath] -> Bool
131− isSrc components = (last components) == "src"
132118
133119generateCode :: [String] -> FilePath -> FilePath -> IO ()
134120generateCode opts baseOutpath jsonFile = do
135121 jsonModTime <- getModificationTime jsonFile
136122 let filepath = takeDirectory jsonFile
137123 dirparts = splitDirectories $ filepath
138− mname = (\c -> if c == '.' then '_' else c) <$> last dirparts
124+ mname = last dirparts
139125 basedir = joinPath $ init dirparts
140− mname' = moduleNameToIL' $ T.pack mname
141− possibleFileName = basedir </> outdir </> (T.unpack mname') </> implFileName mname'
126+ mname' = T.pack mname
127+ possibleFileName = basedir </> (T.unpack mname') </> implFileName mname'
142128 exists <- doesFileExist possibleFileName
143129 if exists
144130 then do
@@ -152,7 +138,7 @@ transpile opts baseOutpath jsonFile = do
152138 jsonText <- T.decodeUtf8 <$> B.readFile jsonFile
153139 let module' = jsonToModule $ parseJson jsonText
154140 ((_, foreigns, asts, implHeader, implFooter), _) <- runSupplyT 5 (moduleToIL module' Nothing)
155− let mn = moduleNameToIL $ moduleName module'
141+ let mn = moduleNameToIL' $ moduleName module'
156142 implementation = prettyPrintIL asts
157143 outpath = joinPath [baseOutpath, T.unpack mn]
158144 implPath = outpath </> implFileName mn
@@ -160,19 +146,33 @@ transpile opts baseOutpath jsonFile = do
160146 putStrLn implPath
161147 B.writeFile implPath $ T.encodeUtf8 (implHeader <> implementation <> implFooter)
162148
163−writeRuntimeFiles :: FilePath -> IO ()
164−writeRuntimeFiles baseOutpath = do
165− createDirectoryIfMissing True $ baseOutpath </> "purescript"
166− let runtimeSource = baseOutpath </> "purescript" </> "purescript.go"
167− runtimeExists <- doesFileExist runtimeSource
168− when (not runtimeExists) $ do
169− B.writeFile runtimeSource $(embedFile "runtime/purescript.go")
170−
171−outdir :: FilePath
172−outdir = "src"
149+writeSupportFiles :: FilePath -> IO ()
150+writeSupportFiles baseOutpath = do
151+ currentDir <- getCurrentDirectory
152+ let goModSource = currentDir </> "go.mod"
153+ goModSourceExists <- doesFileExist goModSource
154+ when (not goModSourceExists) $ do
155+ let modText = $(embedFile "support/go.mod.working")
156+ subdir = baseOutpath \\ currentDir
157+ modText' = T.replace "/$OUTPUT" (T.pack subdir) $ T.decodeUtf8 modText
158+ B.writeFile goModSource $ T.encodeUtf8 modText'
159+ createDirectoryIfMissing True baseOutpath
160+ let goModSource = baseOutpath </> "go.mod"
161+ goModSourceExists <- doesFileExist goModSource
162+ when (not goModSourceExists) $ do
163+ B.writeFile goModSource $(embedFile "support/go.mod.output")
164+ createDirectoryIfMissing True $ currentDir </> "purescript-native"
165+ let goModSource = currentDir </> "purescript-native" </> "go.mod"
166+ goModSourceExists <- doesFileExist goModSource
167+ when (not goModSourceExists) $ do
168+ B.writeFile goModSource $(embedFile "support/go.mod.ffi-loader")
169+ let loaderSource = currentDir </> "purescript-native" </> "ffi_loader.go"
170+ loaderSourceExists <- doesFileExist loaderSource
171+ when (not loaderSourceExists) $ do
172+ B.writeFile loaderSource $(embedFile "support/ffi-loader.go")
173173
174174implFileName :: Text -> FilePath
175−implFileName mn = T.unpack $ mn <> ".go"
175+implFileName mn = ((\c -> if c == '.' then '_' else c) <$> T.unpack mn) <> ".go"
176176
177177help :: String
178178help = "Usage: psgo OPTIONS COREFN-FILES\n\