@@ -15,7 +15,7 @@ import qualified SourceSyntax.Declaration as D
1515
1616
1717declaration :: IParser (D.Declaration t v)
18−declaration = alias <|> datatype <|> infixDecl <|> foreignDef <|> definition
18+declaration = alias <|> datatype <|> infixDecl <|> port <|> definition
1919
2020definition :: IParser (D.Declaration t v)
2121definition = D.Definition <$> Expr.def
@@ -56,67 +56,23 @@ infixDecl = do
5656 D.Fixity assoc (read [n]) <$> anyOp
5757
5858
59−foreignDef :: IParser (D.Declaration t v)
60−foreignDef = do
61− try (reserved "foreign")
62− whitespace
63− importEvent <|> exportEvent
64−
65−exportEvent :: IParser (D.Declaration t v)
66−exportEvent = do
67− try (reserved "export") >> padded (reserved "jsevent")
68− eventName <- jsVar
69− whitespace
70− elmVar <- lowVar
71− padded hasType
72− tipe <- Type.expr
73− case tipe of
74− T.Data "Signal" [t] ->
75− case isExportable t of
76− Nothing -> return (D.ExportEvent eventName elmVar tipe)
77− Just err -> fail err
78− _ -> fail "When importing foreign events, the imported value must have type Signal."
79−
80−importEvent :: IParser (D.Declaration t v)
81−importEvent = do
82− try (reserved "import") >> padded (reserved "jsevent")
83− eventName <- jsVar
84− baseValue <- padded Expr.term
85− <?> "Base case for imported signal (signals cannot be undefined)"
86− elmVar <- lowVar <?> "Name of imported signal"
87− padded hasType
88− tipe <- Type.expr
89− case tipe of
90− T.Data "Signal" [t] ->
91− case isExportable t of
92− Nothing -> return (D.ImportEvent eventName baseValue elmVar tipe)
93− Just err -> fail err
94− _ -> fail "When importing foreign events, the imported value must have type Signal."
95−
96−jsVar :: IParser String
97−jsVar = betwixt '"' '"' $ do
98− v <- (:) <$> (letter <|> char '_') <*> many (alphaNum <|> char '_')
99− if Set.notMember v jsReserveds then return v else
100− fail $ "'" ++ v ++
101− "' is not a good name for a importing or exporting JS values."
102−
103−isExportable tipe =
104− case tipe of
105− T.Lambda _ _ ->
106− Just $ "Elm's JavaScript event interface does not yet handle functions. " ++
107− "Only simple values can be imported and exported in this release."
108−
109− T.Data "JSArray" [t] -> isExportable t
110−
111− T.Data name []
112− | any (`List.isSuffixOf` name) jsTypes -> Nothing
113− | otherwise -> Just $ "'" ++ name ++ "' is not an exportable type." ++ msg
114−
115− T.Data name _ ->
116− Just $ "'" ++ name ++ "' is not an exportable type " ++
117− "constructor. Only 'JSArray' is an exportable container."
118−
119− T.Var _ -> Just $ "Cannot export type variables." ++ msg
59+port :: IParser (D.Declaration t v)
60+port =
61+ do try (reserved "port")
62+ whitespace
63+ name <- lowVar
64+ padded hasType
65+ tipe <- Type.expr
66+ expr <- choice [ do try (outPort name)
67+ padded equals
68+ Just <$> Expr.expr
69+ , return Nothing
70+ ]
71+ return $ D.Port name tipe expr
12072 where
121− msg = " The following types are exportable: " ++ List.intercalate ", " jsTypes
122− jsTypes = ["JSString","JSNumber","JSDomNode","JSBool","JSObject"]
73+ outPort name = do
74+ freshLine
75+ reserved "port"
76+ whitespace
77+ name' <- lowVar
78+ if name == name' then return () else fail "different port"