@@ -1,5 +1,8 @@
11{-# LANGUAGE OverloadedStrings #-}
2−module Generate.JavaScript.Expression (generateDef) where
2+module Generate.JavaScript.Expression
3+ ( generateDecl
4+ )
5+ where
36
47import Control.Arrow (second)
58import Control.Monad.State (State, foldM)
@@ -13,7 +16,7 @@ import qualified AST.Expression.Canonical as Can
1316import AST.Expression.Optimized as Opt
1417import qualified AST.Literal as L
1518import qualified AST.Module.Name as ModuleName
16−import qualified AST.Variable as Var
19+import qualified AST.Variable as V
1720import Generate.JavaScript.Helpers as Help
1821import qualified Generate.JavaScript.Builder as JS
1922import qualified Generate.JavaScript.BuiltIn as BuiltIn
@@ -24,6 +27,15 @@ import qualified Optimize.DecisionTree as DT
2427
2528
2629
30+-- GENERATE DECLARATION
31+
32+
33+generateDecl :: ModuleName.Canonical -> Text -> Opt.Def -> State Int [JS.Stmt]
34+generateDecl home name def =
35+ Var.defineGlobal home name <$> generateDef name def
36+
37+
38+
2739-- CODE CHUNKS
2840
2941
@@ -83,23 +95,6 @@ toExpr code =
8395
8496
8597
86−-- DEFINITIONS
87−
88−
89−generateDef :: Maybe ModuleName.Canonical -> Text -> Opt.Def -> State Int [JS.Stmt]
90−generateDef home name def =
91− do jsBody <-
92− case def of
93− Opt.TailDef argNames body ->
94− generateTailFunction name argNames body
95−
96− Opt.Def body ->
97− generateJsExpr body
98−
99− return (Var.define home name jsBody)
100−
101−
102−
10398-- EXPRESSIONS
10499
105100
@@ -111,8 +106,11 @@ generateJsExpr optExpr =
111106generateCode :: Opt.Expr -> State Int Code
112107generateCode expr =
113108 case expr of
114− Var var ->
115− jsExpr $ Var.canonical var
109+ VarLocal name ->
110+ jsExpr $ Var.local name
111+
112+ VarGlobal home name ->
113+ jsExpr $ Var.global home name
116114
117115 Literal lit ->
118116 jsExpr (Literal.literal lit)
@@ -140,8 +138,8 @@ generateCode expr =
140138 do jsFields <- mapM toField fields
141139 jsExpr $ JS.Object jsFields
142140
143− Binop op leftExpr rightExpr ->
144− binop op leftExpr rightExpr
141+ Binop home op leftExpr rightExpr ->
142+ generateBinop home op leftExpr rightExpr
145143
146144 Function args body ->
147145 generateFunction args body
@@ -163,10 +161,9 @@ generateCode expr =
163161 ++ [JS.Continue (Just (JS.Id (Var.safe name)))]
164162
165163 Let defs body ->
166− do let genDef (name, def) = generateDef Nothing name def
167− stmts <- mapM genDef defs
164+ do stmts <- mapM generateLetDef defs
168165 code <- generateCode body
169− jsBlock (concat stmts ++ toStatementList code)
166+ jsBlock (stmts ++ toStatementList code)
170167
171168 If branches finally ->
172169 generateIf branches finally
@@ -239,13 +236,23 @@ generateProgram kind body =
239236
240237
241238
242−-- FUNCTIONS
239+-- DEFINITIONS
243240
244241
245−generateFunction :: [Text] -> Opt.Expr -> State Int Code
246−generateFunction args body =
247− do code <- generateCode body
248− jsExpr (generateFunctionWithArity args code)
242+generateLetDef :: (Text, Opt.Def) -> State Int JS.Stmt
243+generateLetDef (name, def) =
244+ do jsBody <- generateDef name def
245+ return $ JS.VarDeclStmt [ Help.varDecl name jsBody ]
246+
247+
248+generateDef :: Text -> Opt.Def -> State Int JS.Expr
249+generateDef name def =
250+ case def of
251+ Opt.TailDef argNames body ->
252+ generateTailFunction name argNames body
253+
254+ Opt.Def body ->
255+ generateJsExpr body
249256
250257
251258generateTailFunction :: Text -> [Text] -> Opt.Expr -> State Int JS.Expr
@@ -257,6 +264,16 @@ generateTailFunction name args body =
257264 (JS.While (JS.Bool True) (toStatement code))
258265
259266
267+
268+-- FUNCTIONS
269+
270+
271+generateFunction :: [Text] -> Opt.Expr -> State Int Code
272+generateFunction args body =
273+ do code <- generateCode body
274+ jsExpr (generateFunctionWithArity args code)
275+
276+
260277generateFunctionWithArity :: [Text] -> Code -> JS.Expr
261278generateFunctionWithArity rawArgs code =
262279 let
@@ -283,27 +300,47 @@ generateFunctionWithArity rawArgs code =
283300generateCall :: Opt.Expr -> [Opt.Expr] -> State Int Code
284301generateCall func args =
285302 case (func, args) of
286− (Opt.Var var, [arg]) ->
287− case getUnaryOp var of
288− Just op ->
289− do jsArg <- generateJsExpr arg
290− jsExpr $ JS.Prefix op jsArg
303+ (Opt.VarGlobal home name, [arg]) ->
304+ case name of
305+ "complement" | home == bitwise -> genPrefix JS.PrefixBNot arg
306+ "not" | home == basics -> genPrefix JS.PrefixLNot arg
307+ _ -> generateCallHelp func args
308+
309+ (Opt.VarGlobal home name, [ left, right ]) | home == bitwise ->
310+ case name of
311+ "and" -> genInfix JS.OpBAnd left right
312+ "or" -> genInfix JS.OpBOr left right
313+ "xor" -> genInfix JS.OpBXor left right
314+ "shiftLeftBy" -> genInfix JS.OpLShift right left
315+ "shiftRightBy" -> genInfix JS.OpSpRShift right left
316+ "shiftRightZfBy" -> genInfix JS.OpZfRShift right left
317+ _ -> generateCallHelp func args
291318
292− Nothing ->
293− generateCallHelp func args
319+ _ ->
320+ generateCallHelp func args
294321
295− (Opt.Var var, [ arg1, arg2 ]) ->
296− case getBinaryOp var arg1 arg2 of
297− Just (op, left, right) ->
298− do jsLeft <- generateJsExpr left
299− jsRight <- generateJsExpr right
300− jsExpr $ JS.Infix op jsLeft jsRight
301322
302− Nothing ->
303− generateCallHelp func args
323+genPrefix :: JS.PrefixOp -> Opt.Expr -> State Int Code
324+genPrefix op arg =
325+ do jsArg <- generateJsExpr arg
326+ jsExpr (JS.Prefix op jsArg)
304327
305− _ ->
306− generateCallHelp func args
328+
329+genInfix :: JS.InfixOp -> Opt.Expr -> Opt.Expr -> State Int Code
330+genInfix op left right =
331+ do jsLeft <- generateJsExpr left
332+ jsRight <- generateJsExpr right
333+ jsExpr $ JS.Infix op jsLeft jsRight
334+
335+
336+basics :: ModuleName.Canonical
337+basics =
338+ ModuleName.inCore "Basics"
339+
340+
341+bitwise :: ModuleName.Canonical
342+bitwise =
343+ ModuleName.inCore "Bitwise"
307344
308345
309346generateCallHelp :: Opt.Expr -> [Opt.Expr] -> State Int Code
@@ -321,49 +358,6 @@ generateCallHelp func args =
321358 foldl1 (<|) (jsFunc:jsArgs)
322359
323360
324−getUnaryOp :: Var.Canonical -> Maybe JS.PrefixOp
325−getUnaryOp var =
326− if var == bitwiseComplement then
327− Just JS.PrefixBNot
328−
329− else if var == basicsNot then
330− Just JS.PrefixLNot
331−
332− else
333− Nothing
334−
335−
336−getBinaryOp :: Var.Canonical -> Opt.Expr -> Opt.Expr -> Maybe (JS.InfixOp, Opt.Expr, Opt.Expr)
337−getBinaryOp (Var.Canonical home name) left right =
338− if home /= bitwise then
339− Nothing
340−
341− else
342− case name of
343− "and" -> Just ( JS.OpBAnd, left, right )
344− "or" -> Just ( JS.OpBOr, left, right )
345− "xor" -> Just ( JS.OpBXor, left, right )
346− "shiftLeftBy" -> Just ( JS.OpLShift, right, left )
347− "shiftRightBy" -> Just ( JS.OpSpRShift, right, left )
348− "shiftRightZfBy" -> Just ( JS.OpZfRShift, right, left )
349− _ -> Nothing
350−
351−
352−bitwiseComplement :: Var.Canonical
353−bitwiseComplement =
354− Var.inCore "Bitwise" "complement"
355−
356−
357−basicsNot :: Var.Canonical
358−basicsNot =
359− Var.inCore "Basics" "not"
360−
361−
362−bitwise :: Var.Home
363−bitwise =
364− Var.Module (ModuleName.inCore "Bitwise")
365−
366−
367361
368362-- GENERATE IFS
369363
@@ -495,7 +489,7 @@ edgeToCase exprName labelRoot (test, subTree) =
495489testToExpr :: DT.Test -> JS.Expr
496490testToExpr test =
497491 case test of
498− DT.Constructor (Var.Canonical _ tag) ->
492+ DT.Constructor (V.Canonical _ tag) ->
499493 JS.String tag
500494
501495 DT.Literal (L.Chr char) ->
@@ -525,7 +519,7 @@ pathToTestableExpr root path exampleTest =
525519
526520pathToExpr :: Text -> DT.Path -> Opt.Expr
527521pathToExpr root fullPath =
528− go (Opt.Var (Var.local root)) fullPath
522+ go (Opt.VarLocal root) fullPath
529523 where
530524 go expr path =
531525 case path of
@@ -546,50 +540,36 @@ pathToExpr root fullPath =
546540-- BINARY OPERATORS
547541
548542
549−binop
550− :: Var.Canonical
551− -> Opt.Expr
552− -> Opt.Expr
553− -> State Int Code
554−binop func left right =
555− do jsLeft <- generateJsExpr left
556− jsRight <- generateJsExpr right
557− jsExpr (binopHelp func jsLeft jsRight)
543+generateBinop :: ModuleName.Canonical -> Text -> Opt.Expr -> Opt.Expr -> State Int Code
544+generateBinop home op left right =
545+ do jsLeft <- generateJsExpr left
546+ jsRight <- generateJsExpr right
547+ jsExpr (generateBinopHelp home op jsLeft jsRight)
558548
559549
560550
561551-- BINARY OPERATOR HELPERS
562552
563553
564−binopHelp :: Var.Canonical -> JS.Expr -> JS.Expr -> JS.Expr
565−binopHelp qualifiedOp@(Var.Canonical home op) leftExpr rightExpr =
566− let
567− simpleMake left right =
568− JS.Call (ref "A2") [ Var.canonical qualifiedOp, left, right ]
569− in
570− if home == basicsModule then
571− (Map.findWithDefault simpleMake op basicOps) leftExpr rightExpr
572−
573− else if op == "::" && (home == listModule || home == listModuleInternals) then
574− BuiltIn.cons leftExpr rightExpr
575−
576− else
577− simpleMake leftExpr rightExpr
578−
579−
580−listModule :: Var.Home
581−listModule =
582− Var.Module (ModuleName.inCore "List")
554+generateBinopHelp :: ModuleName.Canonical -> Text -> JS.Expr -> JS.Expr -> JS.Expr
555+generateBinopHelp home op leftExpr rightExpr =
556+ let
557+ simpleMake left right =
558+ JS.Call (ref "A2") [ Var.global home op, left, right ]
559+ in
560+ if home == basics then
561+ (Map.findWithDefault simpleMake op basicOps) leftExpr rightExpr
583562
563+ else if op == "::" && home == list then
564+ BuiltIn.cons leftExpr rightExpr
584565
585−listModuleInternals :: Var.Home
586−listModuleInternals =
587− Var.TopLevel (ModuleName.inCore "List")
566+ else
567+ simpleMake leftExpr rightExpr
588568
589569
590−basicsModule :: Var.Home
591−basicsModule =
592− Var.Module (ModuleName.inCore "Basics")
570+list :: ModuleName.Canonical
571+list =
572+ ModuleName.inCore "List"
593573
594574
595575basicOps :: Map.Map Text (JS.Expr -> JS.Expr -> JS.Expr)