@@ -7,6 +7,9 @@ module CodeGen.IL.Printer
7 , implHeaderSource
7 , implHeaderSource
8 , implFooterSource
8 , implFooterSource
9 , isLiteral
9 , isLiteral
12import Prelude.Compat
15import Prelude.Compat
@@ -30,7 +33,9 @@ import Language.PureScript.Crash
30import Language.PureScript.Names (Ident, runIdent)
33import Language.PureScript.Names (Ident, runIdent)
31import Language.PureScript.Pretty.Common
34import Language.PureScript.Pretty.Common
32import Language.PureScript.PSString (PSString, decodeString, mkString)
35import Language.PureScript.PSString (PSString, decodeString, mkString)
33import CodeGen.IL.Common
37import CodeGen.IL.Common
38+import CodeGen.IL.Optimizer.TCO (tcoLoop)
35import qualified Language.PureScript.Constants as C
40import qualified Language.PureScript.Constants as C
@@ -72,6 +77,7 @@ literals = mkPattern' match'
72 , currentIndent
77 , currentIndent
73 , return $ emit "}"
78 , return $ emit "}"
80+ match (Var _ ident) | ident == C.undefined = return $ emit undefinedName
75 match (Var _ ident) = return $ emit ident
81 match (Var _ ident) = return $ emit ident
76 match (VariableIntroduction _ ident value) = mconcat <$> sequence
82 match (VariableIntroduction _ ident value) = mconcat <$> sequence
77 [ return . emit $ varDecl <> " " <> ident <> " " <> anyType
83 [ return . emit $ varDecl <> " " <> ident <> " " <> anyType
@@ -94,70 +100,42 @@ literals = mkPattern' match'
94 , return $ emit ty
100 , return $ emit ty
95 , return $ emit ")"
101 , return $ emit ")"
97− -- match (App _ (StringLiteral _ u) [arg@Var{}])
98− -- | Just ty <- decodeString u = mconcat <$> sequence
99− -- [ prettyPrintIL' arg
100− -- , return $ emit ".("
101− -- , return $ emit ty
102− -- , return $ emit ")"
104− -- match (App _ (StringLiteral _ u) [arg])
105− -- | Just ty <- decodeString u = mconcat <$> sequence
106− -- [ return $ emit "("
107− -- , prettyPrintIL' arg
108− -- , return $ emit ")"
109− -- , return $ emit ".("
110− -- , return $ emit ty
111− -- , return $ emit ")"
113 match (App _ (Var _ fn) [arg]) | fn == arrayLengthFn = mconcat <$> sequence
103 match (App _ (Var _ fn) [arg]) | fn == arrayLengthFn = mconcat <$> sequence
114− [ return $ emit arrayLengthFn
104+ [ return $ emit fn
115 , return $ emit "("
105 , return $ emit "("
116 , prettyPrintIL' arg
106 , prettyPrintIL' arg
117 , return $ emit ")"
107 , return $ emit ")"
119− -- match (App _ (App _ (App _ (Indexer _ (Var _ fn) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [x]) [y])
120− -- | fnMod == dictMod
121− -- , dictMod == C.dataEq || dictMod == C.dataOrd
122− -- , Just op <- renderOp fn
123− -- , Just t <- unboxType dict
124− -- = mconcat <$> sequence
109+ match (App _ (Var _ fn) args) | fn == indexFn = mconcat <$> sequence
125− -- [ return $ emit $ unbox' t x
110+ [ return $ emit fn
126− -- , return $ emit op
111+ , return $ emit "("
127− -- , return $ emit $ unbox' t y
112+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
129− -- match (App _ (App _ (App _ (Indexer _ (Var _ fn) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [x]) [y])
130− -- | not (isLiteral x) && not (isLiteral y)
131− -- , fnMod == dictMod
132− -- , dictMod == C.dataSemiring || dictMod == C.dataRing ||
133− -- dictMod == C.dataEuclideanRing || dictMod == C.dataHeytingAlgebra
134− -- , Just op <- renderOp fn
135− -- , Just t <- unboxType dict
136− -- = mconcat <$> sequence
115+ match (App _ (Var _ fn) args) | fn == tcoLoop = mconcat <$> sequence
137− -- [ return $ emit $ unbox' t x
116+ [ return $ emit fn
138− -- , return $ emit op
117+ , return $ emit "("
139− -- , return $ emit $ unbox' t y
118+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
141− -- match (App _ (App _ (Indexer _ (Var _ fn) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [n])
121+ match (App _ (App Nothing (StringLiteral Nothing fnx) [fn@Function{}]) args)
142− -- | fnMod == dictMod
122+ | Just ftype <- decodeString fnx
143− -- , dictMod == C.dataRing
145− -- , Just t <- unboxType dict
146− -- = mconcat <$> sequence
123+ , "Fn" `T.isPrefixOf` ftype = mconcat <$> sequence
147− -- [ return $ emit "-("
125+ , return $ emit "("
148− -- , return $ emit $ unbox' t n
126+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
149− -- , return $ emit ")"
127+ , return $ emit ")"
151− -- match (App _ (App _ (Indexer _ (Var _ fn) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [n])
129+ match (App _ (App Nothing (StringLiteral Nothing fnx) [fn]) args)
152− -- | fnMod == dictMod
130+ | Just ftype <- decodeString fnx
153− -- , dictMod == C.dataHeytingAlgebra
154− -- , fn == properToIL C.not
155− -- , Just t <- unboxType dict
156− -- = mconcat <$> sequence
131+ , "Fn" `T.isPrefixOf` ftype = mconcat <$> sequence
157− -- [ return $ emit "!("
133+ , return $ emit ".("
134+ , return $ emit ftype
158− -- , return $ emit $ unbox' t n
135+ , return $ emit ")("
136+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
159− -- , return $ emit ")"
137+ , return $ emit ")"
161 match app@(App{})
139 match app@(App{})
162 | (val, args) <- unApp app []
140 | (val, args) <- unApp app []
163 , length args > 1
141 , length args > 1
@@ -227,15 +205,36 @@ literals = mkPattern' match'
227 , prettyPrintIL' (Var Nothing $ withPrefix name)
205 , prettyPrintIL' (Var Nothing $ withPrefix name)
228 , return $ emit "()"
206 , return $ emit "()"
230− match (Indexer _ prop val) = mconcat <$> sequence
208+ match (Indexer _ prop@StringLiteral{} val@ObjectLiteral{}) = mconcat <$> sequence
231− [ return $ emit "Get("
232− , prettyPrintIL' val
209+ [ prettyPrintIL' val
233− , return $ emit ", "
210+ , return $ emit "["
234 , prettyPrintIL' prop
211 , prettyPrintIL' prop
235− , return $ emit ")"
212+ , return $ emit "]"
214+ match (Indexer _ prop@StringLiteral{} val) = mconcat <$> sequence
215+ [ prettyPrintIL' val
216+ , return $ emit ".("
217+ , return $ emit dictType
218+ , return $ emit ")["
219+ , prettyPrintIL' prop
222+ match (Indexer _ index val@ArrayLiteral{}) = mconcat <$> sequence
223+ [ prettyPrintIL' val
225+ , prettyPrintIL' index
228+ match (Indexer _ index val) = mconcat <$> sequence
229+ [ prettyPrintIL' val
230+ , return $ emit ".("
231+ , return $ emit arrayType
232+ , return $ emit ")["
233+ , prettyPrintIL' index
237 match (InstanceOf _ val ty) = mconcat <$> sequence
236 match (InstanceOf _ val ty) = mconcat <$> sequence
238− [ return $ emit "Contains("
237+ [ return $ emit "Is("
239 , prettyPrintIL' val
238 , prettyPrintIL' val
240 , return $ emit ", "
239 , return $ emit ", "
241 , prettyPrintIL' ty
240 , prettyPrintIL' ty
@@ -275,55 +274,6 @@ literals = mkPattern' match'
275 , prettyPrintIL' thens
274 , prettyPrintIL' thens
276 , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
275 , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
280− -- match (IfElse _ (Binary _ EqualTo cond (BooleanLiteral Nothing True)) thens elses)
281− -- | (App _ (App _ (App _ (Indexer _ (Var _ _) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [x]) [y]) <- cond
282− -- , fnMod == dictMod
283− -- , dictMod == C.dataEq || dictMod == C.dataOrd
284− -- , Just _ <- unboxTypeInt dict
285− -- = mconcat <$> sequence
286− -- [ return $ emit "if "
287− -- , prettyPrintIL' cond
288− -- , return $ emit " "
289− -- , prettyPrintIL' thens
290− -- , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
292− -- match (IfElse _ (Binary _ EqualTo cond (BooleanLiteral Nothing True)) thens elses) = mconcat <$> sequence
293− -- [ return $ emit "if "
294− -- , prettyPrintIL' (tyAssert cond C.heytingAlgebraBoolean)
295− -- , return $ emit " "
296− -- , prettyPrintIL' thens
297− -- , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
299− -- match (IfElse _ (Binary _ EqualTo cond (BooleanLiteral Nothing False)) thens elses) = mconcat <$> sequence
300− -- [ return $ emit "if !("
301− -- , prettyPrintIL' (tyAssert cond C.heytingAlgebraBoolean)
302− -- , return $ emit ") "
303− -- , prettyPrintIL' thens
304− -- , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
306− -- match (IfElse _ (Binary _ EqualTo x y@(NumericLiteral _ n)) thens elses) = mconcat <$> sequence
307− -- [ return $ emit "if "
308− -- , return $ emit $ unbox' t x
309− -- , return $ emit $ " == "
310− -- , prettyPrintIL' y
311− -- , return $ emit " "
312− -- , prettyPrintIL' thens
313− -- , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
316− -- t | Left _ <- n = int
317− -- | Right _ <- n = float
318− -- match (IfElse _ (Binary _ EqualTo a b@StringLiteral{}) thens elses) = mconcat <$> sequence
319− -- [ return $ emit "if "
320− -- , return $ emit $ unbox' string a
321− -- , return $ emit $ " == "
322− -- , prettyPrintIL' b
323− -- , return $ emit " "
324− -- , prettyPrintIL' thens
325− -- , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
327 match (IfElse _ cond thens elses) = mconcat <$> sequence
277 match (IfElse _ cond thens elses) = mconcat <$> sequence
328 [ return $ emit "if "
278 [ return $ emit "if "
329 , prettyPrintIL' cond
279 , prettyPrintIL' cond
@@ -339,8 +289,6 @@ literals = mkPattern' match'
339 -- match (Throw _ _) = return mempty
289 -- match (Throw _ _) = return mempty
340 match (Throw _ value) = mconcat <$> sequence
290 match (Throw _ value) = mconcat <$> sequence
341 [ return $ emit "panic("
291 [ return $ emit "panic("
342− , return $ emit "\"PatternMatchFailure: \""
343− , return $ emit " + "
344 , prettyPrintIL' value
292 , prettyPrintIL' value
345 , return $ emit ")"
293 , return $ emit ")"
@@ -448,7 +396,7 @@ prettyPrintIL' = A.runKleisli $ runPattern matchValue
448 matchValue = buildPrettyPrinter operators (literals <+> fmap parensPos matchValue)
396 matchValue = buildPrettyPrinter operators (literals <+> fmap parensPos matchValue)
449 operators :: (Emit gen) => OperatorTable PrinterState AST gen
397 operators :: (Emit gen) => OperatorTable PrinterState AST gen
450 operators =
398 operators =
451− OperatorTable [ [ unary New "box" ]
399+ OperatorTable [ [ unary New "?" ]
452 , [ unary Not "!"
400 , [ unary Not "!"
453 , unary BitwiseNot "~"
401 , unary BitwiseNot "~"
454 , unary Positive "+"
402 , unary Positive "+"
@@ -459,8 +407,7 @@ prettyPrintIL' = A.runKleisli $ runPattern matchValue
459 , [ binary Add "+"
407 , [ binary Add "+"
460 , binary Subtract "-" ]
408 , binary Subtract "-" ]
461 , [ binary ShiftLeft "<<"
409 , [ binary ShiftLeft "<<"
462− , binary ShiftRight ">>"
410+ , binary ShiftRight ">>" ]
463− , binary ZeroFillShiftRight ">>>" ]
464 , [ binary LessThan "<"
411 , [ binary LessThan "<"
465 , binary LessThanOrEqualTo "<="
412 , binary LessThanOrEqualTo "<="
466 , binary GreaterThan ">"
413 , binary GreaterThan ">"
@@ -499,19 +446,25 @@ interfaceSource :: Text -> [(Text,Bool)] -> [Ident] -> Text
499interfaceSource _ _ _ = ""
446interfaceSource _ _ _ = ""
501implHeaderSource :: Text -> [Text] -> Text -> Text
448implHeaderSource :: Text -> [Text] -> Text -> Text
502−implHeaderSource mn imports _ =
449+implHeaderSource mn imports otherPrefix =
503 "// Code generated by psgo. DO NOT EDIT.\n\n" <>
450 "// Code generated by psgo. DO NOT EDIT.\n\n" <>
504− "package " <> (if mn == "Main" then "main" else mn) <> "\n\n" <>
451+ "package " <> (if mn == "Main" || mn == "Test_Main" then "main" else mn) <> "\n\n" <>
505− "import . \"purescript\"\n" <>
452+ "import . \"" <> runtime <> "\"\n" <>
506− (if mn == "Main"
453+ (if mn == "Main" || mn == "Test_Main"
507− then "import \"ffi\"\n"
454+ then "import _ \"" <> otherPrefix <> "/" <> ffiLoader <> "\"\n"
508− else "") <>
455+ else "\n") <>
509− T.concat imports <> "\n" <>
457+ (T.concat $ formatImport <$> imports) <> ")\n\n" <>
510− "type IGNORE_UNUSED_IMPORTS = bool\n" <>
458+ "type _ = Any\n\n"
511− "type _ = IGNORE_UNUSED_RUNTIME\n" <>
459+ where
512− (if mn == "Main"
460+ formatImport :: Text -> Text
513− then "\nconst _ = ffi.Loader\n\n"
461+ formatImport s =
514− else "\n")
462+ "\t\"" <> otherPrefix <> "/" <> modPrefix <> "/" <> moduleRenamer s <> "\"\n"
463+ moduleRenamer :: Text -> Text
465+ | (s', sfx) <- T.breakOn moduleRenamerMarker s,
466+ not $ T.null sfx = s'
516implFooterSource :: Text -> [Ident] -> Text
469implFooterSource :: Text -> [Ident] -> Text
517implFooterSource mn foreigns =
470implFooterSource mn foreigns =
@@ -519,7 +472,7 @@ implFooterSource mn foreigns =
519 (if null foreigns
472 (if null foreigns
521 else ("// Foreign values\n\n" <>
474 else ("// Foreign values\n\n" <>
522− "var " <> foreignDict <> " = " <> dictType <> "{}\n\n" <>
475+ "var " <> foreignDict <> " = "<> foreignMod <> "(\"" <> mn <> "\")\n\n" <>
523 (T.concat $ (\foreign' ->
476 (T.concat $ (\foreign' ->
524 let name = moduleIdentToIL foreign' in
477 let name = moduleIdentToIL foreign' in
525 varDecl <> " " <> initName name <> " Once\n" <>
478 varDecl <> " " <> initName name <> " Once\n" <>
@@ -529,17 +482,17 @@ implFooterSource mn foreigns =
529 "() Any { \n" <>
482 "() Any { \n" <>
530 " " <> initName name <> ".Do(func() {\n" <>
483 " " <> initName name <> ".Do(func() {\n" <>
531 " " <> valueName name <> " = " <>
484 " " <> valueName name <> " = " <>
532− "SafeGet(" <> foreignDict <> ", " <>
485+ "Get(" <> foreignDict <> ", " <>
533− (stringLiteral $ mkString name) <> ")\n" <>
486+ (stringLiteral . mkString $ runIdent foreign') <> ")\n" <>
534 " })\n" <>
487 " })\n" <>
535 " return " <> valueName name <> "\n" <>
488 " return " <> valueName name <> "\n" <>
536 "}\n\n") <$> foreigns))) <>
489 "}\n\n") <$> foreigns))) <>
537− if mn == "Main" then mainSource else "\n"
490+ if mn == "Main" || mn == "Test.Main" then mainSource else "\n"
539 mainSource :: Text
492 mainSource :: Text
540 mainSource = "\
493 mainSource = "\
541 \func main() {\n\
494 \func main() {\n\
542− \ Run(PS__main())\n\
495+ \ Run(Ꞌmain())\n\
@@ -549,11 +502,26 @@ varDecl = "var"
549renderArg :: Text -> Text -> Text
502renderArg :: Text -> Text -> Text
550renderArg decl arg = arg <> " " <> decl
503renderArg decl arg = arg <> " " <> decl
506+foreignMod = "Foreign"
552foreignDict :: Text
508foreignDict :: Text
553−foreignDict = "Foreign"
509+foreignDict = "foreign"
512+modLabel = "purescript-native"
515+modPrefix = modLabel <> "/output"
518+runtime = "github.com/" <> modLabel <> "/go-runtime"
521+ffiLoader = modLabel <> "/ffi-loader"
555initName :: Text -> Text
523initName :: Text -> Text
556−initName s = "ₒ" <> s
524+initName s = "ᛌ" <> s <> "_once"
558valueName :: Text -> Text
526valueName :: Text -> Text
559−valueName s = "ₐ" <> s
527+valueName s = "ᛧ" <> s