{-# LANGUAGE DeriveDataTypeable #-}

module Development.Duplo.Types.JavaScript where

import Control.Exception (Exception)
import Control.Monad.State.Lazy (State)
import Data.List (intercalate)
import Data.Typeable (Typeable)
import Language.JavaScript.Parser (JSNode(..))

data JSCompilerException = ModuleNotFoundException ModuleName
                         | CircularDependencyException [ModuleName]
                         | ParseException [String]
                         -- When the compiler itself is buggy
                         | InternalParserException String
                         -- When language-javascript somehow produces
                         -- a malformed AST
                         | LanguageJavaScriptException JSNode
  deriving (Typeable)

instance Exception JSCompilerException

instance Show JSCompilerException where
    show (ParseException e) =
      "You have some syntax error in your JavaScript:\n" ++ unlines e
    show (CircularDependencyException names) =
      "Your module dependencies form a cycle:\n" ++ intercalate " => " names
    show (ModuleNotFoundException name) =
      "The module \"" ++ name ++ "\" is not found."
    show (InternalParserException e) =
      "Uh oh. The parser itself is misbehaving: " ++ e
    show (LanguageJavaScriptException element) =
      "language-javascript is not parsing the file correctly:\n" ++ show element

type LineNumber = Int
type ModuleName = String
type DepScore = Int
-- A module consists of its name, its dependencies by names, and the node
-- itself.
data Module = Module
            { _name         :: ModuleName
            , _dependencies :: [ModuleName]
            , _node         :: JSNode
            , _score        :: Maybe DepScore
            } deriving (Show)

type OrderedModules = State [Module]