{-# OPTIONS_GHC -W #-}
module Generate.JavaScript.Variable where

import qualified AST.Helpers as Help
import qualified AST.Variable as Var
import qualified Data.Set as Set
import qualified Generate.JavaScript.Helpers as JS
import qualified Language.ECMAScript3.Syntax as JS

swap :: Char -> Char -> Char -> Char
swap from to c = if c == from then to else c

canonical :: Var.Canonical -> JS.Expression ()
canonical (Var.Canonical home name) =
  case Help.isOp name of
    True  -> JS.BracketRef () (JS.obj (home' ++ ["_op"])) (JS.string name)
    False -> JS.obj (home' ++ [ varName name ])
  where
    home' =
      case home of
        Var.Local       -> []
        Var.BuiltIn     -> []
        Var.Module path -> [ moduleName path ]

moduleName :: String -> String
moduleName x = '$' : map (swap '.' '$') x

varName :: String -> String
varName x = map (swap '\'' '$') x'
    where
      x' = if Set.member x jsReserveds then '$' : x else x

value :: String -> String -> JS.Expression ()
value home name =
    canonical (Var.Canonical (Var.Module home) name)

jsReserveds :: Set.Set String
jsReserveds = Set.fromList
    [ "null", "undefined", "Nan", "Infinity", "true", "false", "eval"
    , "arguments", "int", "byte", "char", "goto", "long", "final", "float"
    , "short", "double", "native", "throws", "boolean", "abstract", "volatile"
    , "transient", "synchronized", "function", "break", "case", "catch"
    , "continue", "debugger", "default", "delete", "do", "else", "finally"
    , "for", "function", "if", "in", "instanceof", "new", "return", "switch"
    , "this", "throw", "try", "typeof", "var", "void", "while", "with", "class"
    , "const", "enum", "export", "extends", "import", "super", "implements"
    , "interface", "let", "package", "private", "protected", "public"
    , "static", "yield"
    -- reserved by the Elm runtime system
    , "Elm", "ElmRuntime"
    , "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9"
    , "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9"
    ]