@@ -7,9 +7,6 @@ module CodeGen.IL.Printer
77 , implHeaderSource
88 , implFooterSource
99 , isLiteral
10− , modLabel
11− , modPrefix
12− , ffiLoader
1310 ) where
1411
1512import Prelude.Compat
@@ -18,6 +15,7 @@ import Control.Arrow ((<+>))
1815import Control.Monad (forM, mzero)
1916import Control.Monad.State (StateT, evalStateT)
2017import Control.PatternArrows
18+import Data.Char (isAscii)
2119import Data.List (filter, (\\))
2220import qualified Control.Arrow as A
2321
@@ -33,9 +31,7 @@ import Language.PureScript.Crash
3331import Language.PureScript.Names (Ident, runIdent)
3432import Language.PureScript.Pretty.Common
3533import Language.PureScript.PSString (PSString, decodeString, mkString)
36−
3734import CodeGen.IL.Common
38−import CodeGen.IL.Optimizer.TCO (tcoLoop)
3935
4036import qualified Language.PureScript.Constants as C
4137
@@ -53,23 +49,26 @@ literals = mkPattern' match'
5349 match (BooleanLiteral _ True) = return $ emit "true"
5450 match (BooleanLiteral _ False) = return $ emit "false"
5551 match (ArrayLiteral _ xs) = mconcat <$> sequence
56− [ return . emit $ arrayType <> "{"
52+ [ return . emit $ arrayType <> "{ "
5753 , intercalate (emit ", ") <$> forM xs prettyPrintIL'
58− , return $ emit "}"
54+ , return $ emit " }"
5955 ]
6056 -- match (ObjectLiteral _ []) = return $ emit "std::initializer_list<std::pair<const string, boxed>>{}"
6157 match (ObjectLiteral _ ps) = mconcat <$> sequence
62− [ return . emit $ dictType <> "{"
58+ [ return . emit $ dictType <> "{\n"
6359 , withIndent $ do
6460 ils <- forM ps $ \(key, value) -> do
6561 value' <- prettyPrintIL' value
66− return $ objectPropertyToString key <> value'
67− return $ intercalate (emit " ") $ map (<> emit ",") ils
62+ return $ emit "{ " <> objectPropertyToString key <> value' <> emit " }"
63+ indentString <- currentIndent
64+ return $ intercalate (emit ",\n") $ map (indentString <>) ils
65+ , return $ emit "\n"
66+ , currentIndent
6867 , return $ emit "}"
6968 ]
7069 where
7170 objectPropertyToString :: (Emit gen) => PSString -> gen
72− objectPropertyToString s = emit $ stringLiteral s <> ": "
71+ objectPropertyToString s = emit $ stringLiteral s <> ", "
7372 match (Block _ sts) = mconcat <$> sequence
7473 [ return $ emit "{\n"
7574 , withIndent $ prettyStatements sts
@@ -77,10 +76,9 @@ literals = mkPattern' match'
7776 , currentIndent
7877 , return $ emit "}"
7978 ]
80− match (Var _ ident) | ident == C.undefined = return $ emit undefinedName
8179 match (Var _ ident) = return $ emit ident
8280 match (VariableIntroduction _ ident value) = mconcat <$> sequence
83− [ return . emit $ varDecl <> " " <> ident <> " " <> anyType
81+ [ return $ emit $ "boxed " <> ident
8482 , maybe (return mempty) (fmap (emit " = " <>) . prettyPrintIL') value
8583 ]
8684 match (Assignment _ target value) = mconcat <$> sequence
@@ -89,195 +87,163 @@ literals = mkPattern' match'
8987 , prettyPrintIL' value
9088 ]
9189 match (App _ val []) = mconcat <$> sequence
92− [ return $ emit "Run("
93− , prettyPrintIL' val
94− , return $ emit ")"
95− ]
96− match (App _ (StringLiteral _ u) [arg])
97− | Just ty <- decodeString u = mconcat <$> sequence
98− [ prettyPrintIL' arg
99− , return $ emit ".("
100− , return $ emit ty
101− , return $ emit ")"
102− ]
103− match (App _ (Var _ fn) [arg]) | fn == arrayLengthFn = mconcat <$> sequence
104− [ return $ emit fn
105− , return $ emit "("
106− , prettyPrintIL' arg
107− , return $ emit ")"
108− ]
109− match (App _ (Var _ fn) args) | fn == indexFn = mconcat <$> sequence
110− [ return $ emit fn
111− , return $ emit "("
112− , intercalate (emit ", ") <$> forM args prettyPrintIL'
113− , return $ emit ")"
114− ]
115− match (App _ (Var _ fn) args) | fn == tcoLoop = mconcat <$> sequence
116− [ return $ emit fn
117− , return $ emit "("
118− , intercalate (emit ", ") <$> forM args prettyPrintIL'
119− , return $ emit ")"
120− ]
121− match (App _ (App Nothing (StringLiteral Nothing fnx) [fn@Function{}]) args)
122− | Just ftype <- decodeString fnx
123− , "Fn" `T.isPrefixOf` ftype = mconcat <$> sequence
124− [ prettyPrintIL' fn
125− , return $ emit "("
126− , intercalate (emit ", ") <$> forM args prettyPrintIL'
127− , return $ emit ")"
128− ]
129− match (App _ (App Nothing (StringLiteral Nothing fnx) [fn]) args)
130− | Just ftype <- decodeString fnx
131− , "Fn" `T.isPrefixOf` ftype = mconcat <$> sequence
132− [ prettyPrintIL' fn
133− , return $ emit ".("
134− , return $ emit ftype
135− , return $ emit ")("
136− , intercalate (emit ", ") <$> forM args prettyPrintIL'
137− , return $ emit ")"
90+ [ prettyPrintIL' val
91+ , return $ emit "()"
13892 ]
139− match app@(App{})
140− | (val, args) <- unApp app []
141− , length args > 1
93+ match (App ss (App _ (App _ (Indexer _ (Var _ fn) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [x]) [y])
94+ | fnMod == dictMod
95+ , dictMod == C.dataEq || dictMod == C.dataSemiring || dictMod == C.dataRing ||
96+ dictMod == C.dataEuclideanRing || dictMod == C.dataHeytingAlgebra
97+ , Just op <- renderOp fn
98+ , Just t <- unboxType dict
14299 = mconcat <$> sequence
143− [ return $ emit "Apply("
144− , prettyPrintIL' val
145− , return $ emit ", "
146− , intercalate (emit ", ") <$> forM args prettyPrintIL'
147− , return $ emit ")"
100+ [ return $ emit $ unbox' t x
101+ , return $ emit op
102+ , return $ emit $ unbox' t y
103+ ]
104+ match (App _ (App _ (Indexer _ (Var _ fn) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [n])
105+ | fnMod == dictMod
106+ , dictMod == C.dataRing
107+ , fn == C.negate
108+ , Just t <- unboxType dict
109+ = mconcat <$> sequence
110+ [ return $ emit "-"
111+ , return $ emit $ unbox' t n
112+ ]
113+ match (App _ (App _ (Indexer _ (Var _ fn) (Var _ fnMod)) [Indexer _ (Var _ dict) (Var _ dictMod)]) [n])
114+ | fnMod == dictMod
115+ , dictMod == C.dataHeytingAlgebra
116+ , fn == properToIL C.not
117+ , Just t <- unboxType dict
118+ = mconcat <$> sequence
119+ [ return $ emit "!"
120+ , return $ emit $ unbox' t n
148121 ]
149122 match (App _ val args) = mconcat <$> sequence
150− [ return $ emit "Apply("
151− , prettyPrintIL' val
152− , return $ emit ", "
123+ [ prettyPrintIL' val
124+ , return $ emit "("
153125 , intercalate (emit ", ") <$> forM args prettyPrintIL'
154126 , return $ emit ")"
155127 ]
156128 match (Function _ (Just name) [] (Block _ [Return _ ret]))
157− | isComplexLiteral ret = mconcat <$> sequence
158− [ return $ emit "\n"
159− , return . emit $ varDecl <> " " <> initName name <> " Once\n"
160− , prettyPrintIL' $ VariableIntroduction Nothing (valueName name) Nothing
161− , return $ emit "\n\n"
162− , return $ emit "func "
163− , return . emit $ withPrefix name
164− , return . emit $ "() " <> anyType <> " "
129+ | isLiteral ret = mconcat <$> sequence
130+ [ return $ emit "auto "
131+ , return $ emit name
132+ , return $ emit "() -> const boxed& "
165133 , return $ emit "{\n"
166134 , withIndent $ do
167− indentString <- currentIndent
168− return $ indentString <> (emit $ initName name <> ".Do(func() {\n") <>
169− indentString <> indentString <> (emit $ valueName name <> " = ")
135+ indentString <- currentIndent
136+ return $ indentString <> emit staticValueBegin
170137 , withIndent $ do
171138 case ret of
172139 Function _ Nothing args body -> mconcat <$> sequence
173− [ return $ emit "func("
174− , return . emit $ intercalate ", " (renderArg anyType <$> args)
175− , return . emit $ ") " <> anyType <> " "
140+ [ return $ emit "[]("
141+ , return $ emit $ intercalate ", " (renderArg <$> args)
142+ , return $ emit ") -> boxed "
176143 , prettyPrintIL' body
177144 ]
178145 _ -> do
179146 prettyPrintIL' ret
180− , return $ emit "\n"
147+ , return $ emit ";\n"
181148 , withIndent $ do
182− indentString <- currentIndent
183− return $ indentString <> (emit $ "})\n" <> "return " <> valueName name <>"\n")
184− , return $ emit "}\n\n"
149+ indentString <- currentIndent
150+ return $ indentString <> emit staticValueEnd
151+ , return $ emit "\n}"
185152 ]
186153 match (Function _ (Just name) [] ret) = mconcat <$> sequence
187− [ return $ emit "func "
188− , return . emit $ withPrefix name
189− , return . emit $ "() " <> anyType <> " "
154+ [ return $ emit "auto "
155+ , return $ emit name
156+ , return $ emit "() -> boxed "
190157 , prettyPrintIL' ret
191158 ]
192− match (Function _ _ args ret) = mconcat <$> sequence
193− [ return $ emit "func("
194− , return . emit $ intercalate ", " (renderArg anyType <$> args)
195− , return . emit $ ") " <> anyType <> " "
159+ match (Function _ name args ret) = mconcat <$> sequence
160+ [ return $ emit captures
161+ , return $ emit "("
162+ , return $ emit $ intercalate ", " (render <$> args)
163+ , return $ emit ") -> boxed "
196164 , prettyPrintIL' ret
197165 ]
198− match (Indexer _ (Var _ name) (Var _ "")) = mconcat <$> sequence
199− [ prettyPrintIL' (Var Nothing $ withPrefix name)
200− , return $ emit "()"
201− ]
202− match (Indexer _ (Var _ name) val) = mconcat <$> sequence
166+ where
167+ (captures, render)
168+ | name == Just tcoLoop = ("[&]", renderArgByVal)
169+ | otherwise = ("[=]", renderArg)
170+ match (Indexer _ prop@(Var _ name) val) = mconcat <$> sequence
203171 [ prettyPrintIL' val
204− , return $ emit "."
205− , prettyPrintIL' (Var Nothing $ withPrefix name)
172+ , return $ emit "::"
173+ , prettyPrintIL' prop
206174 , return $ emit "()"
207175 ]
208− match (Indexer _ prop@StringLiteral{} val@ObjectLiteral{}) = mconcat <$> sequence
176+ match (Indexer _ prop val) = mconcat <$> sequence
209177 [ prettyPrintIL' val
210178 , return $ emit "["
211179 , prettyPrintIL' prop
212180 , return $ emit "]"
213181 ]
214− match (Indexer _ prop@StringLiteral{} val) = mconcat <$> sequence
215− [ prettyPrintIL' val
216− , return $ emit ".("
217− , return $ emit dictType
218− , return $ emit ")["
219− , prettyPrintIL' prop
220− , return $ emit "]"
221− ]
222− match (Indexer _ index val@ArrayLiteral{}) = mconcat <$> sequence
223− [ prettyPrintIL' val
224− , return $ emit "["
225− , prettyPrintIL' index
226− , return $ emit "]"
227− ]
228− match (Indexer _ index val) = mconcat <$> sequence
229− [ prettyPrintIL' val
230− , return $ emit ".("
231− , return $ emit arrayType
232− , return $ emit ")["
233− , prettyPrintIL' index
234− , return $ emit "]"
235− ]
236182 match (InstanceOf _ val ty) = mconcat <$> sequence
237− [ return $ emit "Is("
238− , prettyPrintIL' val
239− , return $ emit ", "
183+ [ return . emit $ unbox' dictType val
184+ , return $ emit ".contains("
240185 , prettyPrintIL' ty
241186 , return $ emit ")"
242187 ]
243188 match (While _ cond sts) = mconcat <$> sequence
244− [ return $ emit "for "
189+ [ return $ emit "while ("
245190 , prettyPrintIL' cond
246− , return $ emit " "
191+ , return $ emit ") "
247192 , prettyPrintIL' sts
248193 ]
249194 match (For _ ident start end sts) = mconcat <$> sequence
250− [ return $ emit $ "for var " <> ident <> " = "
195+ [ return $ emit $ "for (boxed " <> ident <> " = "
251196 , prettyPrintIL' start
252197 , return $ emit $ "; " <> ident <> " < "
253198 , prettyPrintIL' end
254− , return $ emit $ "; " <> ident <> "++ "
199+ , return $ emit $ "; " <> ident <> "++) "
255200 , prettyPrintIL' sts
256201 ]
257202 match (ForIn _ ident obj sts) = mconcat <$> sequence
258− [ return $ emit $ "for var " <> ident <> " in "
203+ [ return $ emit $ "for (boxed " <> ident <> " in "
259204 , prettyPrintIL' obj
260− , return $ emit " "
205+ , return $ emit ") "
261206 , prettyPrintIL' sts
262207 ]
263− match (IfElse _ (Binary _ EqualTo cond@Binary{} (BooleanLiteral Nothing True)) thens elses) = mconcat <$> sequence
264− [ return $ emit "if "
265− , prettyPrintIL' cond
266− , return $ emit " "
208+ match (IfElse _ (Binary _ EqualTo cond (BooleanLiteral Nothing True)) thens elses) = mconcat <$> sequence
209+ [ return $ emit "if ("
210+ , return $ emit $ unbox' "bool" cond
211+ , return $ emit ") "
267212 , prettyPrintIL' thens
268213 , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
269214 ]
270− match (IfElse _ (Binary _ EqualTo cond@Binary{} (BooleanLiteral Nothing False)) thens elses) = mconcat <$> sequence
271− [ return $ emit "if !("
272− , prettyPrintIL' cond
215+ match (IfElse _ (Binary _ EqualTo cond (BooleanLiteral Nothing False)) thens elses) = mconcat <$> sequence
216+ [ return $ emit "if (!("
217+ , return $ emit $ unbox' "bool" cond
218+ , return $ emit ")) "
219+ , prettyPrintIL' thens
220+ , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
221+ ]
222+ match (IfElse _ (Binary _ EqualTo x y@(NumericLiteral _ n)) thens elses) = mconcat <$> sequence
223+ [ return $ emit "if ("
224+ , return $ emit $ unbox' t x
225+ , return $ emit $ " == "
226+ , prettyPrintIL' y
227+ , return $ emit ") "
228+ , prettyPrintIL' thens
229+ , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
230+ ]
231+ where
232+ t | Left _ <- n = int
233+ | Right _ <- n = float
234+ match (IfElse _ (Binary _ EqualTo a b@StringLiteral{}) thens elses) = mconcat <$> sequence
235+ [ return $ emit "if ("
236+ , return $ emit $ unbox' string a
237+ , return $ emit $ " == "
238+ , prettyPrintIL' b
273239 , return $ emit ") "
274240 , prettyPrintIL' thens
275241 , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
276242 ]
277243 match (IfElse _ cond thens elses) = mconcat <$> sequence
278− [ return $ emit "if "
244+ [ return $ emit "if ("
279245 , prettyPrintIL' cond
280− , return $ emit " "
246+ , return $ emit ") "
281247 , prettyPrintIL' thens
282248 , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
283249 ]
@@ -285,10 +251,11 @@ literals = mkPattern' match'
285251 [ return $ emit "return "
286252 , prettyPrintIL' value
287253 ]
288− match (ReturnNoResult _) = return . emit $ "return " <> undefinedName
254+ match (ReturnNoResult _) = return $ emit "return undefined"
289255 -- match (Throw _ _) = return mempty
290256 match (Throw _ value) = mconcat <$> sequence
291− [ return $ emit "panic("
257+ [ return $ emit "THROW_("
258+ , return $ emit "\"PatternMatchFailure: \""
292259 , prettyPrintIL' value
293260 , return $ emit ")"
294261 ]
@@ -328,7 +295,7 @@ literals = mkPattern' match'
328295 Nothing -> ""
329296
330297unary' :: (Emit gen) => UnaryOperator -> (AST -> Text) -> Operator PrinterState AST gen
331−unary' op mkStr = Wrap match (<>)
298+unary' op mkStr = Wrap match (const)
332299 where
333300 match :: (Emit gen) => Pattern PrinterState AST (gen, AST)
334301 match = mkPattern match'
@@ -337,7 +304,7 @@ unary' op mkStr = Wrap match (<>)
337304 match' _ = Nothing
338305
339306unary :: (Emit gen) => UnaryOperator -> Text -> Operator PrinterState AST gen
340−unary op str = unary' op (const str)
307+unary op str = unary' op (\v -> str <> "(" <> prettyPrintIL1 v <> ")")
341308
342309negateOperator :: (Emit gen) => Operator PrinterState AST gen
343310negateOperator = unary' Negate (\v -> if isNegate v then "- " else "-")
@@ -363,21 +330,11 @@ isLiteral ObjectLiteral{} = True
363330isLiteral ArrayLiteral{} = True
364331isLiteral _ = False
365332
366−isComplexLiteral :: AST -> Bool
367−-- isComplexLiteral Function{} = True
368−isComplexLiteral ObjectLiteral{} = True
369−isComplexLiteral ArrayLiteral{} = True
370−isComplexLiteral _ = False
371−
372−unApp :: AST -> [AST] -> (AST, [AST])
373−unApp (App _ val [arg]) args = unApp val (arg : args)
374−unApp other args = (other, args)
375−
376333prettyStatements :: (Emit gen) => [AST] -> StateT PrinterState Maybe gen
377334prettyStatements sts = do
378335 ils <- forM sts prettyPrintIL'
379336 indentString <- currentIndent
380− return $ intercalate (emit "\n") $ map (indentString <>) ils
337+ return $ intercalate (emit "\n") $ map ((<> emit ";") . (indentString <>)) ils
381338
382339-- | Generate a pretty-printed string representing a collection of C++ expressions at the same indentation level
383340prettyPrintILWithSourceMaps :: [AST] -> (Text, [SMap])
@@ -396,7 +353,7 @@ prettyPrintIL' = A.runKleisli $ runPattern matchValue
396353 matchValue = buildPrettyPrinter operators (literals <+> fmap parensPos matchValue)
397354 operators :: (Emit gen) => OperatorTable PrinterState AST gen
398355 operators =
399− OperatorTable [ [ unary New "?" ]
356+ OperatorTable [ [ unary New "box" ]
400357 , [ unary Not "!"
401358 , unary BitwiseNot "~"
402359 , unary Positive "+"
@@ -407,7 +364,8 @@ prettyPrintIL' = A.runKleisli $ runPattern matchValue
407364 , [ binary Add "+"
408365 , binary Subtract "-" ]
409366 , [ binary ShiftLeft "<<"
410− , binary ShiftRight ">>" ]
367+ , binary ShiftRight ">>"
368+ , binary ZeroFillShiftRight ">>>" ]
411369 , [ binary LessThan "<"
412370 , binary LessThanOrEqualTo "<="
413371 , binary GreaterThan ">"
@@ -425,12 +383,15 @@ prettyPrintIL1 :: AST -> Text
425383prettyPrintIL1 = maybe (internalError "Incomplete pattern") runPlainString . flip evalStateT (PrinterState 0) . prettyPrintIL'
426384
427385stringLiteral :: PSString -> Text
428−stringLiteral pss | Just s <- decodeString pss = stringLiteral' s
386+stringLiteral pss | Just s <- decodeString pss =
387+ (if T.all isAscii s
388+ then ""
389+ else ("u8")) <> stringLiteral' s
429390 where
430391 stringLiteral' :: Text -> Text
431392 stringLiteral' s = "\"" <> T.concatMap encodeChar s <> "\""
432393 encodeChar :: Char -> Text
433− encodeChar '\0' = "\\x00"
394+ encodeChar '\0' = "\\0"
434395 encodeChar '\b' = "\\b"
435396 encodeChar '\t' = "\\t"
436397 encodeChar '\n' = "\\n"
@@ -442,29 +403,62 @@ stringLiteral pss | Just s <- decodeString pss = stringLiteral' s
442403 encodeChar c = T.singleton $ c
443404stringLiteral _ = "\"\\uFFFD\""
444405
406+unbox' :: Text -> AST -> Text
407+unbox' _ v@(NumericLiteral{}) = prettyPrintIL1 v
408+unbox' _ v@(BooleanLiteral{}) = prettyPrintIL1 v
409+unbox' _ v@(StringLiteral{}) = prettyPrintIL1 v
410+unbox' t v = unbox t <> "(" <> prettyPrintIL1 v <> ")"
411+
412+unboxType :: Text -> Maybe Text
413+unboxType t
414+ | t == C.eqInt ||
415+ t == C.semiringInt ||
416+ t == C.ringInt
417+ = Just int
418+ | t == C.semiringNumber ||
419+ t == C.ringNumber ||
420+ t == C.euclideanRingNumber
421+ = Just float
422+ | t == C.heytingAlgebraBoolean
423+ = Just bool
424+ | otherwise = Nothing
425+
426+renderOp :: Text -> Maybe Text
427+renderOp op
428+ | op == C.eq = Just " == "
429+ | op == C.notEq = Just " != "
430+ | op == C.add = Just " + "
431+ | op == C.sub = Just " - "
432+ | op == C.mul = Just " * "
433+ | op == C.div = Just " / "
434+ | op == C.conj = Just " && "
435+ | op == C.disj = Just "|| "
436+ | otherwise = Nothing
437+
445438interfaceSource :: Text -> [(Text,Bool)] -> [Ident] -> Text
446−interfaceSource _ _ _ = ""
439+interfaceSource mn values foreigns =
440+ let foreigns' = identToIL <$> foreigns
441+ valueNames = fst <$> values
442+ values' = filter ((`notElem` foreigns') . fst) values ++
443+ zip (foreigns' \\ valueNames) (repeat True)
444+ in
445+ "// Generated by psil compiler\n\n" <>
446+ "#ifndef " <> mn <> "_H\n" <>
447+ "#define " <> mn <> "_H\n\n" <>
448+ "#include \"purescript.h\"\n\n" <>
449+ "namespace " <> mn <> " {\n\n" <>
450+ "using namespace purescript;\n\n" <>
451+ (T.concat $ (\(export, static) ->
452+ let rty = if static then "const boxed&" else "boxed" in
453+ "auto " <> export <> "() -> " <> rty <> ";\n") <$> values') <> "\n" <>
454+ "} // end namespace " <> mn <> "\n\n" <>
455+ "#endif // " <> mn <> "_H\n\n"
447456
448457implHeaderSource :: Text -> [Text] -> Text -> Text
449−implHeaderSource mn imports otherPrefix =
450− "// Code generated by psgo. DO NOT EDIT.\n\n" <>
451− "package " <> (if mn == "Main" || mn == "Test_Main" then "main" else mn) <> "\n\n" <>
452− "import . \"" <> runtime <> "\"\n" <>
453− (if mn == "Main" || mn == "Test_Main"
454− then "import _ \"" <> otherPrefix <> "/" <> ffiLoader <> "\"\n"
455− else "\n") <>
456− "import (\n" <>
457− (T.concat $ formatImport <$> imports) <> ")\n\n" <>
458− "type _ = Any\n\n"
459− where
460− formatImport :: Text -> Text
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
458+implHeaderSource mn imports interfaceImport =
459+ T.concat imports <> "\n"<>
460+ interfaceImport <> "\n\n" <>
461+ "namespace " <> mn <> " {\n\n"
468462
469463implFooterSource :: Text -> [Ident] -> Text
470464implFooterSource mn foreigns =
@@ -472,56 +466,50 @@ implFooterSource mn foreigns =
472466 (if null foreigns
473467 then ""
474468 else ("// Foreign values\n\n" <>
475− "var " <> foreignDict <> " = "<> foreignMod <> "(\"" <> mn <> "\")\n\n" <>
476− (T.concat $ (\foreign' ->
477− let name = moduleIdentToIL foreign' in
478− varDecl <> " " <> initName name <> " Once\n" <>
479− varDecl <> " " <> valueName name <> " " <> anyType <> "\n\n" <>
480− "func " <>
481− withPrefix name <>
482− "() Any { \n" <>
483− " " <> initName name <> ".Do(func() {\n" <>
484− " " <> valueName name <> " = " <>
485− "Get(" <> foreignDict <> ", " <>
486− (stringLiteral . mkString $ runIdent foreign') <> ")\n" <>
487− " })\n" <>
488− " return " <> valueName name <> "\n" <>
489− "}\n\n") <$> foreigns))) <>
490− if mn == "Main" || mn == "Test.Main" then mainSource else "\n"
469+ "DEFINE_FOREIGN_DICTIONARY_AND_ACCESSOR()\n\n" <>
470+ (T.concat $ (\foreign' -> "auto " <>
471+ identToIL foreign' <>
472+ "() -> const boxed& { " <>
473+ staticValueBegin <>
474+ foreignDict <> "().at(" <>
475+ (stringLiteral . mkString $ runIdent foreign') <> "); " <>
476+ staticValueEnd <>
477+ " };\n") <$> foreigns) <>
478+ "\n")) <>
479+ "} // end namespace " <> mn <>
480+ "\n\n" <>
481+ if mn == "Main" then mainSource else "\n"
491482 where
492483 mainSource :: Text
493484 mainSource = "\
494− \func main() {\n\
495− \ Run(Ꞌmain())\n\
485+ \int main(int argc, const char * argv[]) {\n\
486+ \ Main::main()();\n\
487+ \ return 0;\n\
496488 \}\n\n\
497489 \"
498490
499491varDecl :: Text
500−varDecl = "var"
492+varDecl = "const boxed"
501493
502−renderArg :: Text -> Text -> Text
503−renderArg decl arg = arg <> " " <> decl
494+varRefDecl :: Text
495+varRefDecl = varDecl <> "&"
504496
505−foreignMod :: Text
506−foreignMod = "Foreign"
497+renderArg' :: Text -> Text -> Text
498+renderArg' decl arg
499+ | arg == unusedName = decl
500+ | otherwise = decl <> " " <> arg
507501
508−foreignDict :: Text
509−foreignDict = "foreign"
502+renderArg :: Text -> Text
503+renderArg = renderArg' varRefDecl
510504
511−modLabel :: Text
512−modLabel = "purescript-native"
505+renderArgByVal :: Text -> Text
506+renderArgByVal = renderArg' varDecl
513507
514−modPrefix :: Text
515−modPrefix = modLabel <> "/output"
516−
517−runtime :: Text
518−runtime = "github.com/" <> modLabel <> "/go-runtime"
519−
520−ffiLoader :: Text
521−ffiLoader = modLabel <> "/ffi-loader"
508+foreignDict :: Text
509+foreignDict = "foreign"
522510
523−initName :: Text -> Text
524−initName s = "ᛌ" <> s <> "_once"
511+staticValueBegin :: Text
512+staticValueBegin = "static const boxed _ = "
525513
526−valueName :: Text -> Text
527−valueName s = "ᛧ" <> s
514+staticValueEnd :: Text
515+staticValueEnd = "return _;"