@@ -11,7 +11,7 @@ import qualified Text.PrettyPrint.Leijen as PP
1111
1212import qualified AST.Expression.General as Expr
1313import AST.Expression.Optimized as Opt
14−import AST.Literal
14+import qualified AST.Literal as L
1515import qualified AST.Module as Module
1616import qualified AST.Module.Name as ModuleName
1717import qualified AST.Variable as Var
@@ -195,8 +195,8 @@ generateCode expr =
195195 If branches finally ->
196196 generateIf branches finally
197197
198− Case expr decisionTree branches ->
199− generateCase expr decisionTree branches
198+ Case root decisionTree branches ->
199+ JsBlock <$> generateCase root decisionTree branches
200200
201201 ExplicitList elements ->
202202 do jsElements <- mapM generateJsExpr elements
@@ -215,7 +215,7 @@ generateCode expr =
215215 jsExpr $ DotRef () jsDataExpr (var ("_" ++ show index))
216216
217217 GLShader _uid src _tipe ->
218− jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (Str src))]
218+ jsExpr $ ObjectLit () [(PropString () "src", Literal.literal (L.Str src))]
219219
220220 Port impl ->
221221 case impl of
@@ -319,7 +319,7 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
319319 _ ->
320320 (reverse visitedBranches, finally)
321321
322− (Literal (Boolean True), branch) : _ ->
322+ (Literal (L.Boolean True), branch) : _ ->
323323 crushIfsHelp visitedBranches [] branch
324324
325325 visiting : unvisited ->
@@ -329,12 +329,117 @@ crushIfsHelp visitedBranches unvisitedBranches finally =
329329-- CASE EXPRESSIONS
330330
331331generateCase
332− :: Opt.Expr
332+ :: String
333333 -> DT.DecisionTree Opt.Jump
334334 -> [(Int, Opt.Branch)]
335− -> State Int Code
336−generateCase expr decisionTree branches =
337− error "TODO"
335+ -> State Int [Statement ()]
336+generateCase root decisionTree jumpBranches =
337+ do decider <- generateDecisionTree root decisionTree
338+ foldM (goto root) decider jumpBranches
339+
340+
341+goto :: String -> [Statement ()] -> (Int, Opt.Branch) -> State Int [Statement ()]
342+goto root decider (target, branch) =
343+ let
344+ deciderStmt =
345+ LabelledStmt ()
346+ (targetLabel root target)
347+ (DoWhileStmt () (BlockStmt () decider) (BoolLit () False))
348+ in
349+ do stmts <- generateBranch root branch
350+ return (deciderStmt : stmts)
351+
352+
353+targetLabel :: String -> Int -> Id ()
354+targetLabel root target =
355+ Id () (root ++ "_" ++ show target)
356+
357+
358+generateDecisionTree :: String -> DT.DecisionTree Opt.Jump -> State Int [Statement ()]
359+generateDecisionTree root decisionTree =
360+ case decisionTree of
361+ DT.Match (Opt.Inline branch) ->
362+ generateBranch root branch
363+
364+ DT.Match (Opt.Jump target) ->
365+ return [ BreakStmt () (Just (targetLabel root target)) ]
366+
367+ DT.Decision testPath edges fallback ->
368+ do accessExpr <- generateJsExpr (pathToExpr root testPath)
369+
370+ let testExpr =
371+ case fst (head edges) of
372+ DT.Constructor _ ->
373+ DotRef () accessExpr (Id () "ctor")
374+
375+ DT.Literal _ ->
376+ accessExpr
377+
378+ caseClauses <- mapM (edgeToCaseClause root) edges
379+ caseDefault <- fallbackToDefault root fallback
380+
381+ return [ SwitchStmt () testExpr (caseClauses ++ caseDefault) ]
382+
383+
384+edgeToCaseClause :: String -> (DT.Test, DT.DecisionTree Opt.Jump) -> State Int (CaseClause ())
385+edgeToCaseClause root (test, subTree) =
386+ CaseClause () (testToExpr test) <$> generateDecisionTree root subTree
387+
388+
389+testToExpr :: DT.Test -> Expression ()
390+testToExpr test =
391+ case test of
392+ DT.Constructor (Var.Canonical _ tag) ->
393+ StringLit () tag
394+
395+ DT.Literal (L.Chr char) ->
396+ StringLit () [char]
397+
398+ DT.Literal lit ->
399+ Literal.literal lit
400+
401+
402+fallbackToDefault :: String -> Maybe (DT.DecisionTree Opt.Jump) -> State Int [CaseClause ()]
403+fallbackToDefault root fallback =
404+ case fallback of
405+ Nothing ->
406+ return []
407+
408+ Just subTree ->
409+ do stmts <- generateDecisionTree root subTree
410+ return [ CaseDefault () stmts ]
411+
412+
413+generateBranch :: String -> Opt.Branch -> State Int [Statement ()]
414+generateBranch root (Opt.Branch substitutions expr) =
415+ do subts <- mapM (loadPath root) substitutions
416+ code <- generateCode expr
417+ return (subts ++ toStatementList code)
418+
419+
420+loadPath :: String -> (String, DT.Path) -> State Int (Statement ())
421+loadPath root (name, path) =
422+ do jsAccessExpr <- generateJsExpr (pathToExpr root path)
423+ return $ VarDeclStmt () [ varDecl name jsAccessExpr ]
424+
425+
426+pathToExpr :: String -> DT.Path -> Opt.Expr
427+pathToExpr root fullPath =
428+ go (Opt.Var (Var.local root)) fullPath
429+ where
430+ go expr path =
431+ case path of
432+ DT.Position index subpath ->
433+ go (Opt.DataAccess expr index) subpath
434+
435+ DT.Field field subpath ->
436+ go (Opt.Access expr field) subpath
437+
438+ DT.Empty ->
439+ expr
440+
441+ DT.Alias ->
442+ expr
338443
339444
340445-- BINARY OPERATORS