@@ -1,5 +1,8 @@
1{-# LANGUAGE OverloadedStrings #-}
1{-# LANGUAGE OverloadedStrings #-}
2−module Generate.JavaScript.Expression (generateDef) where
2+module Generate.JavaScript.Expression
4import Control.Arrow (second)
7import Control.Arrow (second)
5import Control.Monad.State (State, foldM)
8import Control.Monad.State (State, foldM)
@@ -13,7 +16,7 @@ import qualified AST.Expression.Canonical as Can
13import AST.Expression.Optimized as Opt
16import AST.Expression.Optimized as Opt
14import qualified AST.Literal as L
17import qualified AST.Literal as L
15import qualified AST.Module.Name as ModuleName
18import qualified AST.Module.Name as ModuleName
16−import qualified AST.Variable as Var
19+import qualified AST.Variable as V
17import Generate.JavaScript.Helpers as Help
20import Generate.JavaScript.Helpers as Help
18import qualified Generate.JavaScript.Builder as JS
21import qualified Generate.JavaScript.Builder as JS
19import qualified Generate.JavaScript.BuiltIn as BuiltIn
22import qualified Generate.JavaScript.BuiltIn as BuiltIn
@@ -24,6 +27,15 @@ import qualified Optimize.DecisionTree as DT
30+-- GENERATE DECLARATION
33+generateDecl :: ModuleName.Canonical -> Text -> Opt.Def -> State Int [JS.Stmt]
34+generateDecl home name def =
35+ Var.defineGlobal home name <$> generateDef name def
27-- CODE CHUNKS
39-- CODE CHUNKS
@@ -83,23 +95,6 @@ toExpr code =
89−generateDef :: Maybe ModuleName.Canonical -> Text -> Opt.Def -> State Int [JS.Stmt]
90−generateDef home name def =
93− Opt.TailDef argNames body ->
94− generateTailFunction name argNames body
99− return (Var.define home name jsBody)
103-- EXPRESSIONS
98-- EXPRESSIONS
@@ -111,8 +106,11 @@ generateJsExpr optExpr =
111generateCode :: Opt.Expr -> State Int Code
106generateCode :: Opt.Expr -> State Int Code
112generateCode expr =
107generateCode expr =
113 case expr of
108 case expr of
114− Var var ->
109+ VarLocal name ->
110+ jsExpr $ Var.local name
112+ VarGlobal home name ->
115− jsExpr $ Var.canonical var
113+ jsExpr $ Var.global home name
117 Literal lit ->
115 Literal lit ->
118 jsExpr (Literal.literal lit)
116 jsExpr (Literal.literal lit)
@@ -140,8 +138,8 @@ generateCode expr =
140 do jsFields <- mapM toField fields
138 do jsFields <- mapM toField fields
141 jsExpr $ JS.Object jsFields
139 jsExpr $ JS.Object jsFields
143− Binop op leftExpr rightExpr ->
141+ Binop home op leftExpr rightExpr ->
144− binop op leftExpr rightExpr
142+ generateBinop home op leftExpr rightExpr
146 Function args body ->
144 Function args body ->
147 generateFunction args body
145 generateFunction args body
@@ -163,10 +161,9 @@ generateCode expr =
163 ++ [JS.Continue (Just (JS.Id (Var.safe name)))]
161 ++ [JS.Continue (Just (JS.Id (Var.safe name)))]
165 Let defs body ->
163 Let defs body ->
166− do let genDef (name, def) = generateDef Nothing name def
167− stmts <- mapM genDef defs
164+ do stmts <- mapM generateLetDef defs
168 code <- generateCode body
165 code <- generateCode body
169− jsBlock (concat stmts ++ toStatementList code)
166+ jsBlock (stmts ++ toStatementList code)
171 If branches finally ->
168 If branches finally ->
172 generateIf branches finally
169 generateIf branches finally
@@ -239,13 +236,23 @@ generateProgram kind body =
242−-- FUNCTIONS
239+-- DEFINITIONS
245−generateFunction :: [Text] -> Opt.Expr -> State Int Code
242+generateLetDef :: (Text, Opt.Def) -> State Int JS.Stmt
246−generateFunction args body =
243+generateLetDef (name, def) =
247− do code <- generateCode body
244+ do jsBody <- generateDef name def
248− jsExpr (generateFunctionWithArity args code)
245+ return $ JS.VarDeclStmt [ Help.varDecl name jsBody ]
248+generateDef :: Text -> Opt.Def -> State Int JS.Expr
249+generateDef name def =
251+ Opt.TailDef argNames body ->
252+ generateTailFunction name argNames body
251generateTailFunction :: Text -> [Text] -> Opt.Expr -> State Int JS.Expr
258generateTailFunction :: Text -> [Text] -> Opt.Expr -> State Int JS.Expr
@@ -257,6 +264,16 @@ generateTailFunction name args body =
257 (JS.While (JS.Bool True) (toStatement code))
264 (JS.While (JS.Bool True) (toStatement code))
271+generateFunction :: [Text] -> Opt.Expr -> State Int Code
272+generateFunction args body =
273+ do code <- generateCode body
274+ jsExpr (generateFunctionWithArity args code)
260generateFunctionWithArity :: [Text] -> Code -> JS.Expr
277generateFunctionWithArity :: [Text] -> Code -> JS.Expr
261generateFunctionWithArity rawArgs code =
278generateFunctionWithArity rawArgs code =
@@ -283,27 +300,47 @@ generateFunctionWithArity rawArgs code =
283generateCall :: Opt.Expr -> [Opt.Expr] -> State Int Code
300generateCall :: Opt.Expr -> [Opt.Expr] -> State Int Code
284generateCall func args =
301generateCall func args =
285 case (func, args) of
302 case (func, args) of
286− (Opt.Var var, [arg]) ->
303+ (Opt.VarGlobal home name, [arg]) ->
287− case getUnaryOp var of
304+ case name of
288− Just op ->
305+ "complement" | home == bitwise -> genPrefix JS.PrefixBNot arg
289− do jsArg <- generateJsExpr arg
306+ "not" | home == basics -> genPrefix JS.PrefixLNot arg
290− jsExpr $ JS.Prefix op jsArg
307+ _ -> generateCallHelp func args
309+ (Opt.VarGlobal home name, [ left, right ]) | home == bitwise ->
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
293− generateCallHelp func args
320+ generateCallHelp func args
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
302− Nothing ->
323+genPrefix :: JS.PrefixOp -> Opt.Expr -> State Int Code
303− generateCallHelp func args
324+genPrefix op arg =
325+ do jsArg <- generateJsExpr arg
326+ jsExpr (JS.Prefix op jsArg)
306− generateCallHelp func args
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
336+basics :: ModuleName.Canonical
338+ ModuleName.inCore "Basics"
341+bitwise :: ModuleName.Canonical
343+ ModuleName.inCore "Bitwise"
309generateCallHelp :: Opt.Expr -> [Opt.Expr] -> State Int Code
346generateCallHelp :: Opt.Expr -> [Opt.Expr] -> State Int Code
@@ -321,49 +358,6 @@ generateCallHelp func args =
321 foldl1 (<|) (jsFunc:jsArgs)
358 foldl1 (<|) (jsFunc:jsArgs)
324−getUnaryOp :: Var.Canonical -> Maybe JS.PrefixOp
326− if var == bitwiseComplement then
329− else if var == basicsNot then
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
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 )
352−bitwiseComplement :: Var.Canonical
354− Var.inCore "Bitwise" "complement"
357−basicsNot :: Var.Canonical
359− Var.inCore "Basics" "not"
364− Var.Module (ModuleName.inCore "Bitwise")
368-- GENERATE IFS
362-- GENERATE IFS
@@ -495,7 +489,7 @@ edgeToCase exprName labelRoot (test, subTree) =
495testToExpr :: DT.Test -> JS.Expr
489testToExpr :: DT.Test -> JS.Expr
496testToExpr test =
490testToExpr test =
497 case test of
491 case test of
498− DT.Constructor (Var.Canonical _ tag) ->
492+ DT.Constructor (V.Canonical _ tag) ->
499 JS.String tag
493 JS.String tag
501 DT.Literal (L.Chr char) ->
495 DT.Literal (L.Chr char) ->
@@ -525,7 +519,7 @@ pathToTestableExpr root path exampleTest =
526pathToExpr :: Text -> DT.Path -> Opt.Expr
520pathToExpr :: Text -> DT.Path -> Opt.Expr
527pathToExpr root fullPath =
521pathToExpr root fullPath =
528− go (Opt.Var (Var.local root)) fullPath
522+ go (Opt.VarLocal root) fullPath
530 go expr path =
524 go expr path =
531 case path of
525 case path of
@@ -546,50 +540,36 @@ pathToExpr root fullPath =
546-- BINARY OPERATORS
540-- BINARY OPERATORS
549−binop
543+generateBinop :: ModuleName.Canonical -> Text -> Opt.Expr -> Opt.Expr -> State Int Code
550− :: Var.Canonical
544+generateBinop home op left right =
554−binop func left right =
555− do jsLeft <- generateJsExpr left
545+ do jsLeft <- generateJsExpr left
556− jsRight <- generateJsExpr right
546+ jsRight <- generateJsExpr right
557− jsExpr (binopHelp func jsLeft jsRight)
547+ jsExpr (generateBinopHelp home op jsLeft jsRight)
561-- BINARY OPERATOR HELPERS
551-- BINARY OPERATOR HELPERS
564−binopHelp :: Var.Canonical -> JS.Expr -> JS.Expr -> JS.Expr
554+generateBinopHelp :: ModuleName.Canonical -> Text -> JS.Expr -> JS.Expr -> JS.Expr
565−binopHelp qualifiedOp@(Var.Canonical home op) leftExpr rightExpr =
555+generateBinopHelp home op leftExpr rightExpr =
567− simpleMake left right =
557+ simpleMake left right =
568− JS.Call (ref "A2") [ Var.canonical qualifiedOp, left, right ]
558+ JS.Call (ref "A2") [ Var.global home op, left, right ]
570− if home == basicsModule then
560+ if home == basics then
571− (Map.findWithDefault simpleMake op basicOps) leftExpr rightExpr
561+ (Map.findWithDefault simpleMake op basicOps) leftExpr rightExpr
573− else if op == "::" && (home == listModule || home == listModuleInternals) then
574− BuiltIn.cons leftExpr rightExpr
577− simpleMake leftExpr rightExpr
580−listModule :: Var.Home
582− Var.Module (ModuleName.inCore "List")
563+ else if op == "::" && home == list then
564+ BuiltIn.cons leftExpr rightExpr
585−listModuleInternals :: Var.Home
566+ else
586−listModuleInternals =
567+ simpleMake leftExpr rightExpr
587− Var.TopLevel (ModuleName.inCore "List")
590−basicsModule :: Var.Home
570+list :: ModuleName.Canonical
591−basicsModule =
571+list =
592− Var.Module (ModuleName.inCore "Basics")
572+ ModuleName.inCore "List"
595basicOps :: Map.Map Text (JS.Expr -> JS.Expr -> JS.Expr)
575basicOps :: Map.Map Text (JS.Expr -> JS.Expr -> JS.Expr)