Skip to content

Commit 795fbcb

Browse files
committed
Support task ports with optional input.
1 parent 441a453 commit 795fbcb

File tree

7 files changed

+59
-11
lines changed

7 files changed

+59
-11
lines changed

compiler/src/AST/Canonical.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ data Effects
266266
data Port
267267
= Incoming {_freeVars :: FreeVars, _payload :: Type, _func :: Type}
268268
| Outgoing {_freeVars :: FreeVars, _payload :: Type, _func :: Type}
269-
| Task {_freeVars :: FreeVars, _payload :: Type, _func :: Type}
269+
| Task {_freeVars :: FreeVars, _input :: Maybe Type, _payload :: Type, _func :: Type}
270270
deriving (Show)
271271

272272
data Manager

compiler/src/AST/Optimized.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ data Node
142142
| Kernel [K.Chunk] (Set.Set Global)
143143
| PortIncoming Expr (Set.Set Global)
144144
| PortOutgoing Expr (Set.Set Global)
145-
| PortTask Expr (Set.Set Global)
145+
| PortTask (Maybe Expr) Expr (Set.Set Global)
146146

147147
data EffectsType = Cmd | Sub | Fx
148148

@@ -374,7 +374,7 @@ instance Binary Node where
374374
Kernel a b -> putWord8 8 >> put a >> put b
375375
PortIncoming a b -> putWord8 9 >> put a >> put b
376376
PortOutgoing a b -> putWord8 10 >> put a >> put b
377-
PortTask a b -> putWord8 11 >> put a >> put b
377+
PortTask a b c -> putWord8 11 >> put a >> put b >> put c
378378

379379
get =
380380
do
@@ -391,7 +391,7 @@ instance Binary Node where
391391
8 -> liftM2 Kernel get get
392392
9 -> liftM2 PortIncoming get get
393393
10 -> liftM2 PortOutgoing get get
394-
11 -> liftM2 PortTask get get
394+
11 -> liftM3 PortTask get get get
395395
_ -> fail "problem getting Opt.Node binary"
396396

397397
instance Binary EffectsType where

compiler/src/Canonicalize/Effects.hs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ canonicalizePort env (Src.Port (A.At region portName) tipe) =
101101
Result.throw (Error.PortTypeInvalid region portName Error.SubBad)
102102
_ ->
103103
Result.throw (Error.PortTypeInvalid region portName Error.SubBad)
104-
[Can.TType home name taskArgs]
104+
Can.TType home name taskArgs : tipes
105105
| home == ModuleName.platform && name == Name.task ->
106106
case taskArgs of
107107
[] ->
@@ -111,7 +111,18 @@ canonicalizePort env (Src.Port (A.At region portName) tipe) =
111111
[errorType, incomingType] ->
112112
case (checkTaskError errorType, checkPayload incomingType) of
113113
(True, Right ()) ->
114-
Result.ok (portName, Can.Task freeVars incomingType ctipe)
114+
case tipes of
115+
[] ->
116+
Result.ok (portName, Can.Task freeVars Nothing incomingType ctipe)
117+
[input] ->
118+
case checkPayload input of
119+
Right () ->
120+
-- TODO:
121+
Result.ok (portName, Can.Task freeVars (Just input) incomingType ctipe)
122+
Left (badType, err) ->
123+
Result.throw (Error.PortPayloadInvalid region portName badType err)
124+
_ ->
125+
Result.throw (Error.PortTypeInvalid region portName (Error.TaskExtraInputs (length tipes)))
115126
(False, _) ->
116127
Result.throw (Error.PortTypeInvalid region portName Error.TaskBadError)
117128
(_, Left (badType, err)) ->

compiler/src/Generate/JavaScript.hs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,10 @@ addGlobalHelp mode graph global@(Opt.Global home _) state =
230230
(addDeps deps state)
231231
( generatePort mode global "outgoingPort" encoder
232232
)
233-
Opt.PortTask decoder deps ->
233+
Opt.PortTask maybeEncoder decoder deps ->
234234
addStmt
235235
(addDeps deps state)
236-
( generatePort mode global "taskPort" decoder
236+
( generateTaskPort mode global maybeEncoder decoder
237237
)
238238

239239
addStmt :: State -> JS.Stmt -> State
@@ -411,6 +411,30 @@ generatePort mode (Opt.Global home name) makePort converter =
411411
Expr.codeToExpr (Expr.generate mode (\_ _ -> Nothing) home converter)
412412
]
413413

414+
generateTaskPort :: Mode.Mode -> Opt.Global -> Maybe Opt.Expr -> Opt.Expr -> JS.Stmt
415+
generateTaskPort mode (Opt.Global home name) maybeInputConverter outputConverter =
416+
JS.Var
417+
(JsName.fromGlobal home name)
418+
( case maybeInputConverter of
419+
Nothing ->
420+
JS.Call
421+
( JS.Call
422+
(JS.Ref (JsName.fromKernel Name.platform "taskPort"))
423+
[ JS.String (Name.toBuilder name),
424+
JS.Null,
425+
Expr.codeToExpr (Expr.generate mode (\_ _ -> Nothing) home outputConverter)
426+
]
427+
)
428+
[JS.Null]
429+
Just inputConverter ->
430+
JS.Call
431+
(JS.Ref (JsName.fromKernel Name.platform "taskPort"))
432+
[ JS.String (Name.toBuilder name),
433+
Expr.codeToExpr (Expr.generate mode (\_ _ -> Nothing) home inputConverter),
434+
Expr.codeToExpr (Expr.generate mode (\_ _ -> Nothing) home outputConverter)
435+
]
436+
)
437+
414438
-- GENERATE MANAGER
415439

416440
generateManager :: Mode.Mode -> Graph -> Opt.Global -> Opt.EffectsType -> State -> State

compiler/src/Optimize/Module.hs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,16 @@ addPort home name port_ graph =
103103
let (deps, fields, encoder) = Names.run (Port.toEncoder payloadType)
104104
node = Opt.PortOutgoing encoder deps
105105
in addToGraph (Opt.Global home name) node fields graph
106-
Can.Task _ payloadType _ ->
106+
Can.Task _ Nothing payloadType _ ->
107107
let (deps, fields, decoder) = Names.run (Port.toDecoder payloadType)
108-
node = Opt.PortTask decoder deps
108+
node = Opt.PortTask Nothing decoder deps
109+
in addToGraph (Opt.Global home name) node fields graph
110+
Can.Task _ (Just inputType) payloadType _ ->
111+
let (payloadDeps, payloadFields, decoder) = Names.run (Port.toDecoder payloadType)
112+
(inputDeps, inputFields, encoder) = Names.run (Port.toEncoder inputType)
113+
deps = Set.union payloadDeps inputDeps
114+
fields = Map.unionWith (+) payloadFields inputFields
115+
node = Opt.PortTask (Just encoder) decoder deps
109116
in addToGraph (Opt.Global home name) node fields graph
110117

111118
-- HELPER

compiler/src/Reporting/Error/Canonicalize.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@ data PortProblem
9797
| TaskNoArg
9898
| TaskOneArg
9999
| TaskExtraArgs Int
100+
| TaskExtraInputs Int
100101
| TaskBadError
101102
| TaskBadPayload
102103
| NotCmdOrSub
@@ -657,6 +658,11 @@ toReport source err =
657658
D.reflow
658659
"`Task` only accepts two arguments: the error type and the success type."
659660
)
661+
TaskExtraInputs num ->
662+
( "The `" <> Name.toChars name <> "` port is defined with too many function arguments (" <> show num <> ").",
663+
D.reflow
664+
"A task-based port can accept at most 1 argument."
665+
)
660666
TaskBadError ->
661667
( "The `"
662668
<> Name.toChars name

compiler/src/Type/Constrain/Module.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ letPort name port_ makeConstraint =
7070
tipe <- Instantiate.fromSrcType (Map.map VarN vars) srcType
7171
let header = Map.singleton name (A.At A.zero tipe)
7272
CLet (Map.elems vars) [] header CTrue <$> makeConstraint
73-
Can.Task freeVars _ srcType ->
73+
Can.Task freeVars _ _ srcType ->
7474
do
7575
vars <- Map.traverseWithKey (\k _ -> nameToRigid k) freeVars
7676
tipe <- Instantiate.fromSrcType (Map.map VarN vars) srcType

0 commit comments

Comments
 (0)