on master help sign in
Begin switch from current FFI syntax to "port" syntax
commit740702c0d770f891f9eaa0b1fe69fdd8dd0130ff authorEvan Czaplicki <info@elm-lang.org> dateMon 23 Dec 2013, 23:53 (13 years ago) parentfcbd7fd
8 files changed+54−121
compiler/Build/Source.hs+1−2 compiler/Generate/JavaScript.hs+5−25 compiler/Parse/Declaration.hs+20−64 compiler/SourceSyntax/Declaration.hs+14−6 compiler/SourceSyntax/Module.hs+1−2 compiler/Transform/Canonicalize.hs+6−10 compiler/Transform/SafeNames.hs+3−6 compiler/Type/Constrain/Declaration.hs+4−6
compiler/Build/Source.hs+1−2
@@ -56,8 +56,7 @@ build noPrelude interfaces source =
5656 datatypes = [ (name,vars,ctors,ds) | Datatype name vars ctors ds <- decls ],
5757 fixities = [ (assoc,level,op) | Fixity assoc level op <- decls ],
5858 aliases = [ (name,tvs,tipe,ds) | TypeAlias name tvs tipe ds <- decls ],
59− foreignImports = [ (evt,v,name,typ) | ImportEvent evt v name typ <- decls ],
60− foreignExports = [ (evt,name,typ) | ExportEvent evt name typ <- decls ]
59+ ports = [ (name,tipe,maybe) | Port name tipe maybe <- decls ]
6160 }
6261
6362 types <- TI.infer interfaces metaModule
compiler/Generate/JavaScript.hs+5−25
@@ -299,10 +299,9 @@ generate unsafeModule =
299299 , [ IfSingleStmt () thisModule (ReturnStmt () (Just thisModule)) ]
300300 , [ internalImports (List.intercalate "." (names modul)) ]
301301 , concatMap jsImport (imports modul)
302− , concatMap importEvent (foreignImports modul)
302+ , concatMap jsPort (ports modul)
303303 , [ assign ["_op"] (ObjectLit () []) ]
304304 , concat $ evalState (mapM definition . fst . SD.flattenLets [] $ program modul) 0
305− , map exportEvent $ foreignExports modul
306305 , [ jsExports ]
307306 , [ ReturnStmt () (Just thisModule) ]
308307 ]
@@ -332,29 +331,10 @@ generate unsafeModule =
332331
333332 addId js = InfixExpr () OpAdd (string (js++"_")) (obj "_elm.id")
334333
335− importEvent (js,base,elm,_) =
336− [ VarDeclStmt () [ varDecl elm $ obj "Signal.constant" <| evalState (expression base) 0 ]
337− , ExprStmt () $
338− obj "document.addEventListener" `call`
339− [ addId js
340− , function ["_e"]
341− [ ExprStmt () $ obj "_elm.notify" `call` [dotSep [elm,"id"], obj "_e.value"] ]
342− ]
343− ]
344−
345− exportEvent (js,elm,_) =
346− ExprStmt () $
347− ref "A2" `call`
348− [ obj "Signal.lift"
349− , function ["_v"]
350− [ VarDeclStmt () [varDecl "_e" $ obj "document.createEvent" <| string "Event"]
351− , ExprStmt () $
352− obj "_e.initEvent" `call` [ addId js, BoolLit () True, BoolLit () True ]
353− , ExprStmt () $ AssignExpr () OpAssign (LDot () (ref "_e") "value") (ref "_v")
354− , ExprStmt () $ obj "document.dispatchEvent" <| ref "_e"
355− , ReturnStmt () (Just $ ref "_v")
356− ]
357− , ref elm ]
334+ jsPort (name, _, maybe) =
335+ case maybe of
336+ Nothing -> error "in-ports are not defined yet"
337+ Just expr -> error "out-ports are not defined yet"
358338
359339binop span op e1 e2 =
360340 case op of
compiler/Parse/Declaration.hs+20−64
@@ -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"
compiler/SourceSyntax/Declaration.hs+14−6
@@ -10,8 +10,7 @@ data Declaration tipe var
1010 = Definition (Expr.Def tipe var)
1111 | Datatype String [String] [(String,[Type])] [Derivation]
1212 | TypeAlias String [String] Type [Derivation]
13− | ImportEvent String (Expr.LExpr tipe var) String Type
14− | ExportEvent String String Type
13+ | Port String Type (Maybe (Expr.LExpr tipe var))
1514 | Fixity Assoc Int String
1615 deriving (Eq, Show)
1716
@@ -60,11 +59,20 @@ instance Pretty (Declaration t v) where
6059 name' = P.text name <+> P.hsep (map P.text tvars)
6160 alias = P.hang (P.text "type" <+> name' <+> P.equals) 4 (pretty tipe)
6261
63− -- TODO: Actually write out the contained data in these cases.
64− ImportEvent _ _ _ _ -> P.text (show decl)
65− ExportEvent _ _ _ -> P.text (show decl)
66− Fixity _ _ _ -> P.text (show decl)
62+ Port name tipe maybeExpr ->
63+ let port = P.text "port" <+> P.text name in
64+ P.vcat [ port <+> P.colon <+> pretty tipe
65+ , maybe P.empty (\expr -> port <+> P.equals <+> pretty expr) maybeExpr
66+ ]
6767
68+ Fixity assoc prec op -> P.text "infix" <> assoc' <+> P.int prec <+> P.text op
69+ where
70+ assoc' = case assoc of
71+ L -> P.text "l"
72+ N -> P.empty
73+ R -> P.text "r"
74+
75+prettyDeriving :: [Derivation] -> Doc
6876prettyDeriving deriveables =
6977 case deriveables of
7078 [] -> P.empty
compiler/SourceSyntax/Module.hs+1−2
@@ -51,8 +51,7 @@ data MetadataModule t v = MetadataModule {
5151 fixities :: [(Assoc, Int, String)],
5252 aliases :: [Alias],
5353 datatypes :: [ADT],
54− foreignImports :: [(String, LExpr t v, String, Type)],
55− foreignExports :: [(String, String, Type)]
54+ ports :: [(String, Type, Maybe (LExpr t v))]
5655} deriving Show
5756
5857type Interfaces = Map.Map String ModuleInterface
compiler/Transform/Canonicalize.hs+6−10
@@ -57,20 +57,16 @@ metadataModule ifaces modul =
5757 missings -> Left [ P.text $ "The following imports were not found: " ++ List.intercalate ", " missings ]
5858 program' <- rename initialEnv (program modul)
5959 aliases' <- mapM (threeOfFour renameType') (aliases modul)
60− datatypes' <- mapM (threeOfFour (mapM (second (mapM renameType')))) (datatypes modul)
61− exports' <- mapM (third renameType') (foreignExports modul)
62− imports' <- mapM (twoAndFour (rename initialEnv) renameType') (foreignImports modul)
60+ datatypes' <- mapM (threeOfFour (mapM (two2 (mapM renameType')))) (datatypes modul)
61+ ports' <- mapM (two3 renameType') (ports modul)
6362 return $ modul { program = program'
6463 , aliases = aliases'
6564 , datatypes = datatypes'
66− , foreignExports = exports'
67− , foreignImports = imports' }
65+ , ports = ports' }
6866 where
69− second f (a,b) = (,) a `fmap` f b
70− third f (a,b,c) = (,,) a b `fmap` f c
71− threeOfFour f (a,b,c,d) =
72− do c' <- f c
73− return (a,b,c',d)
67+ two2 f (a,b) = (,) a `fmap` f b
68+ two3 f (a,b,c) = (,,) a `fmap` f b `ap` return c
69+ threeOfFour f (a,b,c,d) = (,,,) a b `fmap` f c `ap` return d
7470 twoAndFour f g (a,b,c,d) =
7571 do b' <- f b
7672 d' <- g d
compiler/Transform/SafeNames.hs+3−6
@@ -69,10 +69,7 @@ metadataModule modul =
6969 , datatypes =
7070 let makeSafe (name,tvars,ctors,ds) = (var name, tvars, map (first var) ctors, ds)
7171 in map makeSafe (datatypes modul)
72− , foreignImports =
73− let makeSafe (js,expr,elm,tipe) = (js, expression expr, var elm, tipe)
74− in map makeSafe (foreignImports modul)
75− , foreignExports =
76− let makeSafe (js,elm,tipe) = (js, var elm, tipe)
77− in map makeSafe (foreignExports modul)
72+ , ports =
73+ let makeSafe (name,tipe,expr) = (name, tipe, expression `fmap` expr)
74+ in map makeSafe (ports modul)
7875 }
compiler/Type/Constrain/Declaration.hs+4−6
@@ -53,12 +53,10 @@ toDefs decl =
5353 -- TODO: with the ability to derive code, you may need to generate stuff!
5454 TypeAlias _ _ _ _ -> []
5555
56− ImportEvent _ expr@(L.L s _) name tipe ->
57− [ Src.TypeAnnotation name tipe
58− , Src.Def (P.PVar name) (L.L s $ Src.App (L.L s $ Src.Var "constant") expr) ]
59−
60− ExportEvent _ name tipe ->
61− [ Src.TypeAnnotation name tipe ]
56+ Port name tipe maybe ->
57+ Src.TypeAnnotation name tipe : case maybe of
58+ Nothing -> []
59+ Just expr -> [ Src.Def (P.PVar name) expr ]
6260
6361 -- no constraints are needed for fixity declarations
6462 Fixity _ _ _ -> []