Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse return type annotation of operations #148

Merged
merged 4 commits into from
Sep 27, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion effekt/shared/src/main/scala/effekt/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ object Namer extends Phase[Parsed, NameResolved] {
val eff: Interface = Context.at(interface) { extractControlEffect(resolve(interface)) }

clauses.foreach {
case source.OpClause(op, tparams, params, body, resumeId) =>
case source.OpClause(op, tparams, params, ret, body, resumeId) =>

// try to find the operation in the handled effect:
eff.ops.find { o => o.name.toString == op.name } map { opSym =>
Expand Down
6 changes: 3 additions & 3 deletions effekt/shared/src/main/scala/effekt/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -556,13 +556,13 @@ class EffektParsers(positions: Positions) extends Parsers(positions) {
| (idRef ^^ InterfaceVar.apply) ~ maybeTypeParams ~ implicitResume ~ functionArg ^^ {
case effect ~ tparams ~ resume ~ BlockLiteral(_, vparams, _, body) =>
val synthesizedId = IdRef(effect.id.name)
Implementation(effect, List(OpClause(synthesizedId, tparams, vparams, body, resume) withPositionOf effect))
Implementation(effect, List(OpClause(synthesizedId, tparams, vparams, None, body, resume) withPositionOf effect))
}
)

lazy val defClause: P[OpClause] =
(`def` ~/> idRef) ~ maybeTypeParams ~ valueParamsOpt ~ implicitResume ~ (`=` ~/> functionBody) ^^ {
case id ~ tparams ~ vparams ~ resume ~ body => OpClause(id, tparams, vparams, body, resume)
(`def` ~/> idRef) ~ maybeTypeParams ~ valueParamsOpt ~ (`:` ~/> effectful).? ~ implicitResume ~ (`=` ~/> functionBody) ^^ {
case id ~ tparams ~ vparams ~ ret ~ resume ~ body => OpClause(id, tparams, vparams, ret, body, resume)
}

lazy val clause: P[MatchClause] =
Expand Down
5 changes: 4 additions & 1 deletion effekt/shared/src/main/scala/effekt/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,10 @@ object Typer extends Phase[NameResolved, Typechecked] {
Context.error("Duplicate definitions of operations")

clauses foreach Context.withFocus {
case d @ source.OpClause(op, tparams, params, body, resume) =>
case _ @ source.OpClause(op, tparams, params, Some(ret), body, resumeId) =>
// TODO: Can we somehow use the return type provided by the user?
Context.abort(pretty"Unexpected type annotation on operation ${op}.")
jiribenes marked this conversation as resolved.
Show resolved Hide resolved
case d @ source.OpClause(op, tparams, params, None, body, resume) =>
val declaration = d.definition

val declaredType = Context.lookupFunctionType(declaration)
Expand Down
4 changes: 2 additions & 2 deletions effekt/shared/src/main/scala/effekt/core/Transformer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
val sig = h.definition

New(Handler(sig, sig.ops.map(clauses.apply).map {
case op @ source.OpClause(id, tparams, vparams, body, resume) =>
case op @ source.OpClause(id, tparams, vparams, ret, body, resume) =>
val vps = vparams map transform
// currently the operations don't take block params
val opBlock: BlockLit = BlockLit(vps, transform(body))
Expand Down Expand Up @@ -222,7 +222,7 @@ object Transformer extends Phase[Typechecked, CoreTransformed] {
val clauses = cls.map { cl => (cl.definition, cl) }.toMap

Handler(h.definition, h.definition.ops.map(clauses.apply).map {
case op @ source.OpClause(id, tps, vps, body, resume) =>
case op @ source.OpClause(id, tps, vps, ret, body, resume) =>
val ps = vps map transform

// introduce a block parameter for resume
Expand Down
11 changes: 7 additions & 4 deletions effekt/shared/src/main/scala/effekt/source/Tree.scala
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,10 @@ case class New(impl: Implementation) extends Term


// TODO also allow block params and add a check in TryHandle to rule out continuation capture and block params.
case class OpClause(id: IdRef, tparams: List[Id], vparams: List[ValueParam], body: Stmt, resume: IdDef) extends Reference {

// `ret` is an optional user-provided type annotation for the return type
// currently the annotation is rejected by [[Typer]] -- after that phase, `ret` should always be `None`
case class OpClause(id: IdRef, tparams: List[Id], vparams: List[ValueParam], ret: Option[Effectful], body: Stmt, resume: IdDef) extends Reference {
type symbol = symbols.Operation
}

Expand Down Expand Up @@ -639,8 +642,8 @@ object Tree {
}

def rewrite(h: OpClause)(using C: Context): OpClause = visit(h) {
case OpClause(id, tparams, params, body, resume) =>
OpClause(id, tparams, params, rewrite(body), resume)
case OpClause(id, tparams, params, ret, body, resume) =>
OpClause(id, tparams, params, ret, rewrite(body), resume)
}

def rewrite(c: MatchClause)(using C: Context): MatchClause = visit(c) {
Expand Down Expand Up @@ -790,7 +793,7 @@ object Tree {
}

def query(h: OpClause)(using Context, Ctx): Res = visit(h) {
case OpClause(id, tparams, params, body, resume) =>
case OpClause(id, tparams, params, ret, body, resume) =>
scoped { query(body) }
}

Expand Down
4 changes: 2 additions & 2 deletions effekt/shared/src/main/scala/effekt/typer/PreTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -193,8 +193,8 @@ class BoxUnboxInference {
}

def rewrite(h: OpClause)(using Context): OpClause = visit(h) {
case OpClause(id, tparams, params, body, resume) =>
OpClause(id, tparams, params, rewrite(body), resume)
case OpClause(id, tparams, params, ret, body, resume) =>
OpClause(id, tparams, params, ret, rewrite(body), resume)
}

def rewrite(c: MatchClause)(using Context): MatchClause = visit(c) {
Expand Down