@@ -2,24 +2,27 @@
2module Parse.Declaration where
2module Parse.Declaration where
4import Control.Applicative ((<$>), (<*>))
4import Control.Applicative ((<$>), (<*>))
5−import Data.List (foldl')
5+import qualified Data.List as List
6import Text.Parsec hiding (newline,spaces)
6import Text.Parsec hiding (newline,spaces)
7import Text.Parsec.Indent
7import Text.Parsec.Indent
8import qualified Text.Pandoc as Pan
8import qualified Text.Pandoc as Pan
10import Parse.Helpers
10import Parse.Helpers
11import qualified Parse.Expression as Expr
11import qualified Parse.Expression as Expr
12+import qualified SourceSyntax.Type as T
12import qualified Parse.Type as Type
13import qualified Parse.Type as Type
14import SourceSyntax.Declaration (Declaration(..))
15import SourceSyntax.Declaration (Declaration(..))
16import Unique
17import Unique
19+declaration :: IParser (Declaration t v)
20+declaration = definition <|> alias <|> datatype <|> foreignDef
19definition :: IParser (Declaration t v)
22definition :: IParser (Declaration t v)
20definition = Definition <$> Expr.def
23definition = Definition <$> Expr.def
22−alias :: IParser [Declaration t v]
25+alias :: IParser (Declaration t v)
24 start <- getPosition
27 start <- getPosition
25 reserved "type" <?> "type alias (type Point = {x:Int, y:Int})"
28 reserved "type" <?> "type alias (type Point = {x:Int, y:Int})"
@@ -29,4 +32,95 @@ alias = do
29 whitespace ; string "=" ; whitespace
32 whitespace ; string "=" ; whitespace
30 tipe <- Type.expr
33 tipe <- Type.expr
31 end <- getPosition
34 end <- getPosition
32− return [TypeAlias alias args tipe]
35+ return (TypeAlias alias args tipe)
37+datatype :: IParser (Declaration t v)
39+ reserved "data" <?> "datatype definition (data T = A | B | ...)"
41+ name <- capVar <?> "name of data-type"
42+ args <- spacePrefix lowVar
43+ whitespace ; string "=" ; whitespace
44+ tcs <- pipeSep1 Type.constructor
45+ return $ Datatype name args tcs
48+foreignDef :: IParser (Declaration t v)
50+ try (reserved "foreign")
52+ importEvent <|> exportEvent
54+exportEvent :: IParser (Declaration t v)
56+ try (reserved "export") >> whitespace >> reserved "jsevent" >> whitespace
60+ whitespace ; hasType ; whitespace
63+ T.Data "Signal" [t] ->
64+ case isExportable t of
65+ Nothing -> return (ExportEvent eventName elmVar tipe)
66+ Just err -> error err
67+ _ -> error "When importing foreign events, the imported value must have type Signal."
69+importEvent :: IParser (Declaration t v)
71+ try (reserved "import") >> whitespace >> reserved "jsevent" >> whitespace
74+ baseValue <- Expr.term <?> "Base case for imported signal (signals cannot be undefined)"
76+ elmVar <- lowVar <?> "Name of imported signal"
77+ whitespace ; hasType ; whitespace
80+ T.Data "Signal" [t] ->
81+ case isExportable t of
82+ Nothing -> return (ImportEvent eventName baseValue elmVar tipe)
83+ Just err -> error err
84+ _ -> error "When importing foreign events, the imported value must have type Signal."
86+jsVar :: IParser String
87+jsVar = betwixt '"' '"' $ do
88+ v <- (:) <$> (letter <|> char '_') <*> many (alphaNum <|> char '_')
89+ if v `notElem` jsReserveds then return v else
91+ "' is not a good name for a importing or exporting JS values."
93+jsReserveds :: [String]
95+ [ "null", "undefined", "Nan", "Infinity", "true", "false", "eval"
96+ , "arguments", "int", "byte", "char", "goto", "long", "final", "float"
97+ , "short", "double", "native", "throws", "boolean", "abstract", "volatile"
98+ , "transient", "synchronized", "function", "break", "case", "catch"
99+ , "continue", "debugger", "default", "delete", "do", "else", "finally"
100+ , "for", "function", "if", "in", "instanceof", "new", "return", "switch"
101+ , "this", "throw", "try", "typeof", "var", "void", "while", "with", "class"
102+ , "const", "enum", "export", "extends", "import", "super", "implements"
103+ , "interface", "let", "package", "private", "protected", "public"
110+ Just $ "Elm's JavaScript event interface does not yet handle functions. " ++
111+ "Only simple values can be imported and exported in this release."
113+ T.Data "JSArray" [t] -> isExportable t
116+ | name `elem` jsTypes -> Nothing
117+ | otherwise -> Just $ "'" ++ name ++ "' is not an exportable type." ++ msg
120+ Just $ "'" ++ name ++ "' is not an exportable type " ++
121+ "constructor. Only 'JSArray' is an exportable container."
123+ T.Var _ -> Just $ "Cannot export type variables." ++ msg
125+ msg = " The following types are exportable: " ++ List.intercalate ", " jsTypes
126+ jsTypes = ["JSString","JSNumber","JSDomNode","JSBool","JSObject"]