git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
15 files changed+290−171
since splitsnapshots
unifiedsplit
.gitignore+1−2 README.md+1−1 app/Main.hs+29−8 default.nix+23 package.yaml+6−6 psgo.cabal+145 src/CodeGen/IL.hs+6−46 src/CodeGen/IL/Common.hs+21−19 src/CodeGen/IL/Optimizer.hs+14−1 src/CodeGen/IL/Optimizer/Inliner.hs+3−3 src/CodeGen/IL/Optimizer/TCO.hs+5−5 src/CodeGen/IL/Printer.hs+15−10 src/Tests.hs+5−4 stack.nix+1−1 stack.yaml+15−65
.gitignore+1−2
@@ -12,8 +12,6 @@ cabal.sandbox.config
1212.test_modules/
1313bower_components/
1414node_modules
15−pscpp.cabal
16−psgo.cabal
1715tmp/
1816.stack-work/
1917stack.yaml.lock
@@ -22,3 +20,4 @@ examples/docs/docs/
2220core-tests/full-core-docs.md
2321.psc-ide-port
2422.vscode/
23+result
README.md+1−1
@@ -34,7 +34,7 @@ There are two utilities in the purescript-native "suite": `pscpp` and `psgo`. Th
3434
3535
3636#### For more information and a Getting Started guide, please see
37−* [`pscpp`](https://github.com/andyarvanitis/purescript-native/blob/master/README-cpp.md)
37+* [`pscpp`](https://github.com/andyarvanitis/purescript-native/blob/cpp/README-cpp.md)
3838* [`psgo`](https://github.com/andyarvanitis/purescript-native/blob/golang/README-go.md)
3939
4040
app/Main.hs+29−8
@@ -43,7 +43,7 @@ import CodeGen.IL.Printer
4343
4444import Tests
4545
46−data Command = Build | Run
46+data Command = Build | Run (Maybe String)
4747
4848parseJson :: Text -> Value
4949parseJson text
@@ -54,12 +54,32 @@ jsonToModule :: Value -> Module Ann
5454jsonToModule value =
5555 case parse moduleFromJSON value of
5656 Success (_, r) -> r
57− _ -> error "failed"
57+ _ -> error "Failed parsing corefn. Psgo currently supports purescript <= 0.13.8"
58+
59+splitArgs :: [String] -> ([String], Maybe String, [String])
60+splitArgs args =
61+ let (opts, files) = partition (isPrefixOf "--") args
62+ opts' = (map . map) toLower opts
63+ (moduleName, files') =
64+ if null files
65+ then (Nothing, files)
66+ else
67+ if "--run" `elem` opts' && length (files) >= 1
68+ then do
69+ let file0 = head files
70+ files' = tail files
71+ case file0 of
72+ "Main.main" -> (Just "Main", files')
73+ "Test.Main.main" -> (Just "Test.Main", files')
74+ _ -> (Nothing, files)
75+ else (Nothing, files)
76+ in (opts, moduleName, files')
5877
5978main :: IO ()
6079main = do
6180 args <- getArgs
62− let (opts, files) = partition (isPrefixOf "--") args
81+ -- let (opts, files) = partition (isPrefixOf "--") args
82+ let (opts, moduleName, files) = splitArgs args
6383 opts' = (map . map) toLower opts
6484 if "--tests" `elem` opts'
6585 then runTests
@@ -81,7 +101,7 @@ main = do
81101 else
82102 processFiles opts' files
83103 if "--run" `elem` opts
84− then runBuildTool Run
104+ then runBuildTool $ Run moduleName
85105 else when ("--no-build" `notElem` opts) $
86106 runBuildTool Build
87107 return ()
@@ -109,11 +129,12 @@ main = do
109129 return ()
110130 runBuildTool :: Command -> IO ()
111131 runBuildTool cmd = do
112− let command = case cmd of
113− Build -> "build"
114− Run -> "run"
115132 project <- projectEnv
116− callProcess "go" [command, T.unpack project </> modPrefix' </> "Main"]
133+ case cmd of
134+ Build -> do
135+ callProcess "go" ["build", T.unpack project </> modPrefix' </> "Main"]
136+ Run moduleName -> do
137+ callProcess "go" ["run", T.unpack project </> modPrefix' </> fromMaybe "Main" moduleName]
117138 return ()
118139
119140generateCode :: [String] -> FilePath -> FilePath -> IO ()
default.nixnew file+23
@@ -0,0 +1,23 @@
1+let
2+ haskellNix = import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {};
3+ nixpkgsSrc = haskellNix.sources.nixpkgs-1903; # has hsc2hs-0.68.4
4+
5+ hsc2hsOverlay = self: super: {
6+ buildPackages = super.buildPackages // {
7+ hsc2hs = super.haskellPackages.hsc2hs;
8+ };
9+ };
10+
11+ nixpkgsArgs = haskellNix.nixpkgsArgs // {
12+ overlays = haskellNix.nixpkgsArgs.overlays ++ [ hsc2hsOverlay ];
13+ };
14+in
15+{ pkgs ? import nixpkgsSrc nixpkgsArgs
16+}:
17+
18+pkgs.haskell-nix.stackProject {
19+ src = pkgs.haskell-nix.haskellLib.cleanGit {
20+ name = "purescript-native";
21+ src = ./.;
22+ };
23+}
package.yaml+6−6
@@ -24,7 +24,7 @@ description: Please see the README on Github at <https://github.com/andy
2424dependencies:
2525- base >= 4.7 && < 5
2626- bytestring >= 0.10.8.2 && < 0.11
27−- purescript -any
27+- purescript
2828- base-compat >=0.6.0
2929- protolude >=0.1.6
3030- text
@@ -36,11 +36,11 @@ dependencies:
3636- transformers >=0.3.0 && <0.6
3737- mtl >=2.1.0 && <2.3.0
3838- aeson >=1.0 && <1.5
39−- directory -any
40−- process -any
41−- file-embed -any
42−- filemanip -any
43−- gitrev -any
39+- directory
40+- process
41+- file-embed
42+- filemanip
43+- gitrev
4444
4545library:
4646 source-dirs: src
psgo.cabalnew file+145
@@ -0,0 +1,145 @@
1+cabal-version: 1.12
2+
3+-- This file has been generated from package.yaml by hpack version 0.35.0.
4+--
5+-- see: https://github.com/sol/hpack
6+
7+name: psgo
8+version: 0.1.0.0
9+description: Please see the README on Github at <https://github.com/andyarvanitis/purescript-native#readme>
10+homepage: https://github.com/andyarvanitis/purescript-native#readme
11+bug-reports: https://github.com/andyarvanitis/purescript-native/issues
12+author: Andy Arvanitis
13+maintainer: example@example.com
14+copyright: 2018 Andy Arvanitis
15+license: BSD3
16+license-file: LICENSE
17+build-type: Simple
18+extra-source-files:
19+ README.md
20+ ChangeLog.md
21+ stack.yaml
22+ support/ffi-loader.go
23+ support/go.mod.ffi-loader
24+ support/go.mod.output
25+ support/go.mod.working
26+
27+source-repository head
28+ type: git
29+ location: https://github.com/andyarvanitis/purescript-native
30+
31+library
32+ exposed-modules:
33+ CodeGen.IL
34+ CodeGen.IL.Common
35+ CodeGen.IL.Optimizer
36+ CodeGen.IL.Optimizer.Common
37+ CodeGen.IL.Optimizer.Inliner
38+ CodeGen.IL.Optimizer.MagicDo
39+ CodeGen.IL.Optimizer.TCO
40+ CodeGen.IL.Printer
41+ Tests
42+ other-modules:
43+ Paths_psgo
44+ hs-source-dirs:
45+ src
46+ default-extensions:
47+ ConstraintKinds
48+ DataKinds
49+ DeriveFunctor
50+ EmptyDataDecls
51+ FlexibleContexts
52+ KindSignatures
53+ LambdaCase
54+ MultiParamTypeClasses
55+ NoImplicitPrelude
56+ PatternGuards
57+ PatternSynonyms
58+ RankNTypes
59+ RecordWildCards
60+ OverloadedStrings
61+ ScopedTypeVariables
62+ TupleSections
63+ ViewPatterns
64+ build-depends:
65+ aeson >=1.0 && <1.5
66+ , base >=4.7 && <5
67+ , base-compat >=0.6.0
68+ , bytestring >=0.10.8.2 && <0.11
69+ , containers
70+ , directory
71+ , file-embed
72+ , filemanip
73+ , filepath
74+ , gitrev
75+ , monad-parallel >=0.7.2.2 && <0.8
76+ , mtl >=2.1.0 && <2.3.0
77+ , pattern-arrows >=0.0.2 && <0.1
78+ , process
79+ , protolude >=0.1.6
80+ , purescript
81+ , safe >=0.3.9 && <0.4
82+ , text
83+ , transformers >=0.3.0 && <0.6
84+ default-language: Haskell2010
85+
86+executable psgo
87+ main-is: Main.hs
88+ other-modules:
89+ Paths_psgo
90+ hs-source-dirs:
91+ app
92+ ghc-options: -threaded -rtsopts -with-rtsopts=-N
93+ build-depends:
94+ aeson >=1.0 && <1.5
95+ , base >=4.7 && <5
96+ , base-compat >=0.6.0
97+ , bytestring >=0.10.8.2 && <0.11
98+ , containers
99+ , directory
100+ , file-embed
101+ , filemanip
102+ , filepath
103+ , gitrev
104+ , monad-parallel >=0.7.2.2 && <0.8
105+ , mtl >=2.1.0 && <2.3.0
106+ , pattern-arrows >=0.0.2 && <0.1
107+ , process
108+ , protolude >=0.1.6
109+ , psgo
110+ , purescript
111+ , safe >=0.3.9 && <0.4
112+ , text
113+ , transformers >=0.3.0 && <0.6
114+ default-language: Haskell2010
115+
116+test-suite psgo-test
117+ type: exitcode-stdio-1.0
118+ main-is: Spec.hs
119+ other-modules:
120+ Paths_psgo
121+ hs-source-dirs:
122+ test
123+ ghc-options: -threaded -rtsopts -with-rtsopts=-N
124+ build-depends:
125+ aeson >=1.0 && <1.5
126+ , base >=4.7 && <5
127+ , base-compat >=0.6.0
128+ , bytestring >=0.10.8.2 && <0.11
129+ , containers
130+ , directory
131+ , file-embed
132+ , filemanip
133+ , filepath
134+ , gitrev
135+ , monad-parallel >=0.7.2.2 && <0.8
136+ , mtl >=2.1.0 && <2.3.0
137+ , pattern-arrows >=0.0.2 && <0.1
138+ , process
139+ , protolude >=0.1.6
140+ , psgo
141+ , purescript
142+ , safe >=0.3.9 && <0.4
143+ , text
144+ , transformers >=0.3.0 && <0.6
145+ default-language: Haskell2010
src/CodeGen/IL.hs+6−46
@@ -52,10 +52,7 @@ moduleToIL
5252 -> m (Text, [Text], [AST], Text, Text)
5353moduleToIL (Module _ coms mn _ imps _ foreigns decls) project =
5454 do
55− let usedNames = concatMap getNames decls
56− let mnLookup = renameImports usedNames imps
57− let decls' = renameModules mnLookup decls
58− ilDecls <- mapM (bindToIL ModuleDecl) decls'
55+ ilDecls <- mapM (bindToIL ModuleDecl) decls
5956 optimized <- traverse (traverse (optimize modName')) ilDecls
6057 let optimized' = concat optimized
6158 values = annotValue <$> optimized'
@@ -80,27 +77,6 @@ moduleToIL (Module _ coms mn _ imps _ foreigns decls) project =
8077 getNames (NonRec _ ident _) = [ident]
8178 getNames (Rec vals) = map (snd . fst) vals
8279
83− -- | Creates alternative names for each module to ensure they don't collide
84− -- with declaration names.
85− renameImports :: [Ident] -> [(Ann, ModuleName)] -> M.Map ModuleName (Ann, ModuleName)
86− renameImports = go M.empty
87− where
88− go :: M.Map ModuleName (Ann, ModuleName) -> [Ident] -> [(Ann, ModuleName)] -> M.Map ModuleName (Ann, ModuleName)
89− go acc used ((ann, mn') : mns') =
90− let mni = Ident $ runModuleName mn'
91− in if mn' /= mn && mni `elem` used
92− then let newName = freshModuleName 1 mn' used
93− in go (M.insert mn' (ann, newName) acc) (Ident (runModuleName newName) : used) mns'
94− else go (M.insert mn' (ann, mn') acc) used mns'
95− go acc _ [] = acc
96−
97− freshModuleName :: Integer -> ModuleName -> [Ident] -> ModuleName
98− freshModuleName i mn'@(ModuleName pns) used =
99− let newName = ModuleName $ init pns ++ [ProperName $ runProperName (last pns) <> "_" <> T.pack (show i)]
100− in if Ident (runModuleName newName) `elem` used
101− then freshModuleName (i + 1) mn' used
102− else newName
103−
10480 -- | Generates IL code for a module import
10581 --
10682 importToIL :: AST -> [Text]
@@ -112,25 +88,6 @@ moduleToIL (Module _ coms mn _ imps _ foreigns decls) project =
11288 extract :: Text -> Text
11389 extract = T.replace "_" "." . T.dropWhileEnd (=='_')
11490
115− -- | Replaces the `ModuleName`s in the AST so that the generated code refers to
116− -- the collision-avoiding renamed module imports.
117− renameModules :: M.Map ModuleName (Ann, ModuleName) -> [Bind Ann] -> [Bind Ann]
118− renameModules mnLookup binds =
119− let (f, _, _) = everywhereOnValues id ilExpr goBinder
120− in map f binds
121− where
122− ilExpr :: Expr a -> Expr a
123− ilExpr (Var ann q) = Var ann (renameQual q)
124− ilExpr e = e
125− goBinder :: Binder a -> Binder a
126− goBinder (ConstructorBinder ann q1 q2 bs) = ConstructorBinder ann (renameQual q1) (renameQual q2) bs
127− goBinder b = b
128− renameQual :: Qualified a -> Qualified a
129− renameQual (Qualified (Just mn') a) =
130− let (_,mnSafe) = fromMaybe (internalError "Missing value in mnLookup") $ M.lookup mn' mnLookup
131− in Qualified (Just mnSafe) a
132− renameQual q = q
133−
13491 -- |
13592 -- Generate code in the simplified intermediate representation for a declaration
13693 --
@@ -180,7 +137,7 @@ moduleToIL (Module _ coms mn _ imps _ foreigns decls) project =
180137 updates <- mapM (sndM valueToIL) ps
181138 obj' <- freshName'
182139 let objVar = AST.Var Nothing obj'
183− copy = AST.VariableIntroduction Nothing obj' (Just $ AST.App Nothing (AST.StringLiteral Nothing (mkString dictType)) [obj])
140+ copy = AST.VariableIntroduction Nothing obj' (Just $ copyDict obj)
184141 assign (k, v) = AST.Assignment Nothing (accessorString k objVar) v
185142 sts = copy : (assign <$> updates) ++ [AST.Return Nothing objVar]
186143 return $ AST.App Nothing (AST.Function Nothing Nothing [] (AST.Block Nothing sts)) []
@@ -244,7 +201,7 @@ moduleToIL (Module _ coms mn _ imps _ foreigns decls) project =
244201 -- | Generate code in the simplified intermediate representation for a reference to a
245202 -- variable that may have a qualified name.
246203 qualifiedToIL :: (a -> Ident) -> Qualified a -> AST
247− qualifiedToIL f (Qualified (Just (ModuleName [ProperName mn'])) a) | mn' == C.prim = AST.Var Nothing . moduleIdentToIL $ f a
204+ qualifiedToIL f (Qualified (Just (ModuleName mn')) a) | mn' == C.prim = AST.Var Nothing . moduleIdentToIL $ f a
248205 qualifiedToIL f (Qualified (Just mn') a) | mn /= mn' = AST.Indexer Nothing (AST.Var Nothing . moduleIdentToIL $ f a) (AST.Var Nothing (moduleNameToIL mn'))
249206 qualifiedToIL f (Qualified _ a) = AST.Indexer Nothing (AST.Var Nothing . moduleIdentToIL $ f a) (AST.Var Nothing "")
250207
@@ -359,3 +316,6 @@ emptyAnn = (SourceSpan "" (SourcePos 0 0) (SourcePos 0 0), [], Nothing, Nothing)
359316arrayLength :: AST -> AST
360317arrayLength a = AST.App Nothing (AST.Var Nothing arrayLengthFn) [a]
361318-- arrayLength a = AST.Var Nothing (arrayLengthFn <> "(" <> prettyPrintIL1 a <> ")")
319+
320+copyDict :: AST -> AST
321+copyDict a = AST.App Nothing (AST.Var Nothing copyDictFn) [a]
src/CodeGen/IL/Common.hs+21−19
@@ -16,12 +16,12 @@ import Language.PureScript.Names
1616import qualified Language.PureScript.Constants as C
1717
1818moduleNameToIL :: ModuleName -> Text
19−moduleNameToIL (ModuleName pns) =
20− let name = T.intercalate "_" (runProperName `map` pns)
21− in if nameIsILBuiltIn name then (name <> "_") else name
19+moduleNameToIL (ModuleName mn) =
20+ let name = T.replace "." "_" mn
21+ in if nameIsILBuiltIn name then (name <> moduleRenamerMarker) else name
2222
2323moduleNameToIL' :: ModuleName -> Text
24−moduleNameToIL' (ModuleName pns) = T.intercalate "." (runProperName `map` pns)
24+moduleNameToIL' (ModuleName mn) = T.replace "_" "." mn
2525
2626-- | Convert an 'Ident' into a valid IL identifier:
2727--
@@ -50,16 +50,17 @@ unusedName = "_"
5050
5151properToIL :: Text -> Text
5252properToIL name
53− | nameIsILReserved name || nameIsILBuiltIn name || prefixIsReserved name = name <> "ˉ"
53+ | nameIsILReserved name = "ˉ" <> name
5454 | otherwise = T.concatMap identCharToText name
5555
5656-- | Attempts to find a human-readable name for a symbol, if none has been specified returns the
5757-- ordinal value.
5858identCharToText :: Char -> Text
59+identCharToText 'ṩ' = "_ṩ"
5960identCharToText c | isAlphaNum c = T.singleton c
6061identCharToText '_' = "_"
61−identCharToText '\'' = "ʹ"
62−identCharToText c = "ᵤ" <> T.pack (show (ord c))
62+identCharToText '\'' = "ꞌ" -- lowercase saltillo
63+identCharToText c = error (show (ord c)) -- TODO: should never occur now(?)
6364
6465moduleProperToIL :: Text -> Text
6566moduleProperToIL = T.concatMap identCharToText
@@ -76,12 +77,14 @@ nameIsILBuiltIn name =
7677 [ "Any"
7778 , "Apply"
7879 , "Contains"
80+ , "CopyDict"
7981 , "Dict"
8082 , "EffFn"
8183 , "Fn"
8284 , "Foreign"
8385 , "Get"
8486 , "Index"
87+ , "Is"
8588 , "Length"
8689 , "Once"
8790 , "Run"
@@ -124,16 +127,6 @@ ilKeywords =
124127 , "var"
125128 ]
126129
127−-- moduleIsReserved :: Text -> Bool
128−-- moduleIsReserved "Main" = False
129−-- moduleIsReserved name = not $ T.isInfixOf "_" name
130−
131−prefixIsReserved :: Text -> Bool
132−prefixIsReserved name =
133− any (`T.isPrefixOf` name)
134− [
135− ]
136−
137130ilLiterals :: [Text]
138131ilLiterals =
139132 [ "init"
@@ -159,7 +152,7 @@ ilLiterals =
159152 ]
160153
161154withPrefix :: Text -> Text
162−withPrefix s = "PS__" <> s
155+withPrefix s = "Ꞌ" <> s -- uppercase saltillo
163156
164157anyType :: Text
165158anyType = "Any"
@@ -170,6 +163,9 @@ dictType = "Dict"
170163arrayType :: Text
171164arrayType = "[]" <> anyType
172165
166+uncurriedFnType :: Int -> Text
167+uncurriedFnType i = "Fn" <> (T.pack . show $ i)
168+
173169int :: Text
174170int = "int"
175171
@@ -188,7 +184,13 @@ arrayLengthFn = "Length"
188184indexFn :: Text
189185indexFn = "Index"
190186
187+copyDictFn :: Text
188+copyDictFn = "CopyDict"
189+
191190freshName' :: MonadSupply m => m Text
192191freshName' = do
193192 name <- freshName
194− return $ T.replace "$" "ᵗ" name
193+ return $ T.replace "$" "ṩ" name
194+
195+moduleRenamerMarker :: Text
196+moduleRenamerMarker = "__"
src/CodeGen/IL/Optimizer.hs+14−1
@@ -22,10 +22,11 @@ import qualified Language.PureScript.Constants as C
2222optimize :: MonadSupply m => AST -> AST -> m AST
2323optimize mn il = do
2424 il' <- untilFixedPoint (inlineFnComposition . inlineUnsafeCoerce . inlineUnsafePartial . tidyUp) il
25− untilFixedPoint (return . ignoreUnusedResults . inlineCommonValues . inlineCommonOperators . tidyUp) . tco mn . inlineST
25+ il'' <- untilFixedPoint (return . ignoreUnusedResults . inlineCommonValues . inlineCommonOperators . tidyUp) . tco mn . inlineST
2626 =<< untilFixedPoint (return . magicDoST)
2727 =<< untilFixedPoint (return . magicDoEff)
2828 =<< untilFixedPoint (return . magicDoEffect) il'
29+ untilFixedPoint (return . collapseVarDeclarations) il''
2930 where
3031 tidyUp :: AST -> AST
3132 tidyUp = applyAll
@@ -54,6 +55,18 @@ collapseIfChecks = everywhere collapse where
5455 | prop == "otherwise" && val == "Data_Boolean" = exprs
5556 collapse exprs = exprs
5657
58+collapseVarDeclarations :: AST -> AST
59+collapseVarDeclarations = everywhere collapse where
60+ collapse :: AST -> AST
61+ collapse (Block ss sts) = Block ss (go Nothing sts)
62+ collapse s = s
63+
64+ go :: Maybe Text -> [AST] -> [AST]
65+ go _ [] = []
66+ go Nothing (decl@(VariableIntroduction _ var (Just _)) : sts) = decl : go (Just var) (go Nothing sts)
67+ go (Just var') ((VariableIntroduction ss var (Just val)) : sts)
68+ | var == var' = (Assignment ss (Var Nothing var) val) : go (Just var') sts
69+ go var' (s:sts) = s : go var' sts
5770
5871ignoreUnusedResults :: AST -> AST
5972ignoreUnusedResults = everywhere $ removeFromBlock go
src/CodeGen/IL/Optimizer/Inliner.hs+3−3
@@ -117,7 +117,6 @@ inlineCommonOperators = everywhereTopDown $ applyAll $
117117 , binary' C.dataIntBits C.xor BitwiseXor
118118 , binary' C.dataIntBits C.shl ShiftLeft
119119 , binary' C.dataIntBits C.shr ShiftRight
120− , binary' C.dataIntBits C.zshr ZeroFillShiftRight
121120 , unary' C.dataIntBits C.complement BitwiseNot
122121
123122 , inlineNonClassFunction (isModFn (C.dataFunction, C.apply)) $ \f x -> App Nothing f [x]
@@ -186,13 +185,14 @@ inlineCommonOperators = everywhereTopDown $ applyAll $
186185 runFn :: Int -> AST -> AST
187186 runFn = runFn' C.dataFunctionUncurried C.runFn (\ss f args ->
188187 let len = length args
189− typ = mkString $ "Fn" <> (T.pack . show $ len) in
188+ typ = mkString $ uncurriedFnType len in
190189 if len > 0
191190 then App ss (App Nothing (StringLiteral Nothing typ) [f]) args
192191 else App ss f args)
193192 runEffFn :: Text -> Text -> Int -> AST -> AST
194193 runEffFn modName fnName = runFn' modName fnName $ \ss fn acc ->
195− Function ss Nothing [] (Block ss [Return ss (App ss fn acc)])
194+ let typ = mkString . uncurriedFnType $ length acc in
195+ Function ss Nothing [] (Block ss [Return ss (App ss (App Nothing (StringLiteral Nothing typ) [fn]) acc)])
196196
197197 runFn' :: Text -> Text -> (Maybe SourceSpan -> AST -> [AST] -> AST) -> Int -> AST -> AST
198198 runFn' modName runFnName res n = convert where
src/CodeGen/IL/Optimizer/TCO.hs+5−5
@@ -12,21 +12,21 @@ import CodeGen.IL.Common
1212import qualified Language.PureScript.Constants as C
1313
1414tcoLoop :: Text
15−tcoLoop = "__tco_loop"
15+tcoLoop = "ṩtco_loop"
1616
1717tco :: AST -> AST -> AST
1818tco mn = everywhere convert where
1919 tcoVar :: Text -> Text
20− tcoVar arg = "__tco_var_" <> arg
20+ tcoVar arg = "ṩtco_var_" <> arg
2121
2222 copyVar :: Text -> Text
23− copyVar arg = "__copy_" <> arg
23+ copyVar arg = "ṩcopy_" <> arg
2424
2525 tcoDone :: Text
26− tcoDone = "__tco_done"
26+ tcoDone = "ṩtco_done"
2727
2828 tcoResult :: Text
29− tcoResult = "__tco_result"
29+ tcoResult = "ṩtco_result"
3030
3131 convert :: AST -> AST
3232 convert fn@(Function ss (Just name) args _)
src/CodeGen/IL/Printer.hs+15−10
@@ -234,7 +234,7 @@ literals = mkPattern' match'
234234 , return $ emit "]"
235235 ]
236236 match (InstanceOf _ val ty) = mconcat <$> sequence
237− [ return $ emit "Contains("
237+ [ return $ emit "Is("
238238 , prettyPrintIL' val
239239 , return $ emit ", "
240240 , prettyPrintIL' ty
@@ -407,8 +407,7 @@ prettyPrintIL' = A.runKleisli $ runPattern matchValue
407407 , [ binary Add "+"
408408 , binary Subtract "-" ]
409409 , [ binary ShiftLeft "<<"
410− , binary ShiftRight ">>"
411− , binary ZeroFillShiftRight ">>>" ]
410+ , binary ShiftRight ">>" ]
412411 , [ binary LessThan "<"
413412 , binary LessThanOrEqualTo "<="
414413 , binary GreaterThan ">"
@@ -449,9 +448,9 @@ interfaceSource _ _ _ = ""
449448implHeaderSource :: Text -> [Text] -> Text -> Text
450449implHeaderSource mn imports otherPrefix =
451450 "// Code generated by psgo. DO NOT EDIT.\n\n" <>
452− "package " <> (if mn == "Main" then "main" else mn) <> "\n\n" <>
451+ "package " <> (if mn == "Main" || mn == "Test_Main" then "main" else mn) <> "\n\n" <>
453452 "import . \"" <> runtime <> "\"\n" <>
454− (if mn == "Main"
453+ (if mn == "Main" || mn == "Test_Main"
455454 then "import _ \"" <> otherPrefix <> "/" <> ffiLoader <> "\"\n"
456455 else "\n") <>
457456 "import (\n" <>
@@ -459,7 +458,13 @@ implHeaderSource mn imports otherPrefix =
459458 "type _ = Any\n\n"
460459 where
461460 formatImport :: Text -> Text
462− formatImport s = " \"" <> otherPrefix <> "/" <> modPrefix <> "/" <> s <> "\"\n"
461+ formatImport s =
462+ "\t\"" <> otherPrefix <> "/" <> modPrefix <> "/" <> moduleRenamer s <> "\"\n"
463+ moduleRenamer :: Text -> Text
464+ moduleRenamer s
465+ | (s', sfx) <- T.breakOn moduleRenamerMarker s,
466+ not $ T.null sfx = s'
467+ moduleRenamer s = s
463468
464469implFooterSource :: Text -> [Ident] -> Text
465470implFooterSource mn foreigns =
@@ -482,12 +487,12 @@ implFooterSource mn foreigns =
482487 " })\n" <>
483488 " return " <> valueName name <> "\n" <>
484489 "}\n\n") <$> foreigns))) <>
485− if mn == "Main" then mainSource else "\n"
490+ if mn == "Main" || mn == "Test.Main" then mainSource else "\n"
486491 where
487492 mainSource :: Text
488493 mainSource = "\
489494 \func main() {\n\
490− \ Run(PS__main())\n\
495+ \ Run(Ꞌmain())\n\
491496 \}\n\n\
492497 \"
493498
@@ -516,7 +521,7 @@ ffiLoader :: Text
516521ffiLoader = modLabel <> "/ffi-loader"
517522
518523initName :: Text -> Text
519−initName s = "ₒ" <> s
524+initName s = "ᛌ" <> s <> "_once"
520525
521526valueName :: Text -> Text
522−valueName s = "ₐ" <> s
527+valueName s = "ᛧ" <> s
src/Tests.hs+5−4
@@ -31,7 +31,7 @@ runTests = do
3131 let srcDir = outputDir </> "src"
3232 createDirectory srcDir
3333
34− callProcess "git" ["clone", "--branch", "v0.13.0", "--depth", "1", "https://github.com/purescript/purescript.git"]
34+ callProcess "git" ["clone", "--branch", "v0.13.8", "--depth", "1", "https://github.com/purescript/purescript.git"]
3535 let passingDir = baseDir </> "purescript" </> "tests" </> "purs" </> "passing"
3636 passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passingDir
3737
@@ -63,9 +63,8 @@ runTests = do
6363 callProcess "rm" ["-rf", "output"]
6464 callProcess "rm" ["-rf", "Main"]
6565 callProcess "spago" ["build"]
66− callProcess "psgo" []
6766 --
68− -- Run C++ files
67+ -- Run executable file
6968 --
7069 outputFile <- openFile (tmp </> logpath </> logfile) AppendMode
7170 hPutStrLn outputFile ("\n" ++ inputFile ++ ":")
@@ -114,7 +113,9 @@ fetchPackages :: IO ()
114113-------------------------------------------------------------------------------
115114fetchPackages = do
116115 callProcess "spago" ["init"]
117− callCommand "add_psgo_to_spago_config"
116+ callCommand "sed '$s/\\(}\\)/, backend = \"psgo\"\\1/' < spago.dhall | dhall format > spago.tmp"
117+ callCommand "mv spago.tmp spago.dhall"
118+
118119 mapM (callProcess "spago" . (\p -> ["install", p])) packages
119120 return ()
120121
stack.nix+1−1
@@ -17,7 +17,7 @@
1717
1818pkgs.haskell.lib.buildStackProject {
1919 name = "default-stack-shell";
20− ghc = pkgs.haskell.compiler.ghc864;
20+ ghc = pkgs.haskell.compiler.ghc865;
2121 buildInputs = with pkgs; [git git-lfs gmp ncurses zlib];
2222 LANG = "en_US.UTF-8";
2323}
stack.yaml+15−65
@@ -1,74 +1,24 @@
1−# This file was automatically generated by 'stack init'
2−#
3−# Some commonly used options have been documented as comments in this file.
4−# For advanced use and comprehensive documentation of the format, please see:
5−# https://docs.haskellstack.org/en/stable/yaml_configuration/
1+resolver: lts-13.26
62
7−# Resolver to choose a 'specific' stackage snapshot or a compiler version.
8−# A snapshot resolver dictates the compiler version and the set of packages
9−# to be used for project dependencies. For example:
10−#
11−# resolver: lts-3.5
12−# resolver: nightly-2015-09-21
13−# resolver: ghc-7.10.2
14−# resolver: ghcjs-0.1.0_ghc-7.10.2
15−# resolver:
16−# name: custom-snapshot
17−# location: "./custom-snapshot.yaml"
18−resolver: lts-13.12
19−
20−# User packages to be built.
21−# Various formats can be used as shown in the example below.
22−#
23−# packages:
24−# - some-directory
25−# - https://example.com/foo/bar/baz-0.0.2.tar.gz
26−# - location:
27−# git: https://github.com/commercialhaskell/stack.git
28−# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
29−# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
30−# extra-dep: true
31−# subdirs:
32−# - auto-update
33−# - wai
34−#
35−# A package marked 'extra-dep: true' will only be built if demanded by a
36−# non-dependency (i.e. a user package), and its test suites and benchmarks
37−# will not be run. This is useful for tweaking upstream packages.
383packages:
394- .
40−# Dependency packages to be pulled from upstream that are not in the resolver
41−# (e.g., acme-missiles-0.3)
5+
426extra-deps:
43−- git: https://github.com/purescript/purescript
44− commit: 738aaa2f21097c7f18aa8100b16ae52316addb04
7+- git: https://github.com/purescript/purescript
8+ commit: 9cad73ed8ea7df3011032ddbd2f3de5a0c08629c
9+- happy-1.19.9
10+- language-javascript-0.7.0.0
4511- network-3.0.1.1
46−- pipes-http-1.0.5
47−
48−# Override default flag values for local packages and extra-deps
49−# flags: {}
50−
51−# Extra package databases containing global packages
52−# extra-package-dbs: []
53−
54−# Control whether we use the GHC we find on the path
55−# system-ghc: true
56−#
57−# Require a specific version of stack, using version ranges
58−# require-stack-version: -any # Default
59−# require-stack-version: ">=1.6"
60−#
61−# Override the architecture used by stack, especially useful on Windows
62−# arch: i386
63−# arch: x86_64
64−#
65−# Extra directories used by stack for building
66−# extra-include-dirs: [/path/to/dir]
67−# extra-lib-dirs: [/path/to/dir]
68−#
69−# Allow a newer minor version of GHC than the snapshot specifies
70−# compiler-check: newer-minor
12+- these-1.0.1
13+- semialign-1
7114
7215nix:
16+ enable: false
7317 shell-file: stack.nix
7418
19+flags:
20+ aeson-pretty:
21+ lib-only: true
22+ these:
23+ assoc: false
24+ quickcheck: false