Skip to content

Commit b1dbcfd

Browse files
Merge branch 'hkmc2' into hkmc2
2 parents d313fd5 + 220bfa3 commit b1dbcfd

File tree

7 files changed

+137
-10
lines changed

7 files changed

+137
-10
lines changed

hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ extends Importer:
7272
term(Block(LetLike(`let`, lhs, rhso, N) :: bod :: Nil))
7373
case LetLike(`let`, lhs, S(rhs), N) =>
7474
raise(ErrorReport(
75-
msg"Expected a right-hand side for let bindings in expression position" ->
75+
msg"Expected a body for let bindings in expression position" ->
7676
tree.toLoc :: Nil))
7777
block(LetLike(`let`, lhs, S(rhs), N) :: Nil)._1
7878
case LetLike(`set`, lhs, S(rhs), N) =>
@@ -89,6 +89,23 @@ extends Importer:
8989
term(bod),
9090
), Term.Assgn(lt, sym.ref(id))))
9191
case _ => ??? // TODO error
92+
case Handle(id, cls, blk, S(bod)) =>
93+
term(Block(Handle(id, cls, blk, N) :: bod :: Nil))
94+
case Handle(id: Ident, cls: Ident, Block(sts), N) =>
95+
raise(ErrorReport(
96+
msg"Expected a body for handle bindings in expression position" ->
97+
tree.toLoc :: Nil))
98+
99+
val sym =
100+
fieldOrVarSym(Handler, id)
101+
val newCtx = ctx.copy(locals = ctx.locals + (id.name -> sym))
102+
Term.Handle(sym, term(cls)(using newCtx), ObjBody(block(sts)._1))
103+
104+
case h: Handle =>
105+
raise(ErrorReport(
106+
msg"Unsupported handle binding shape" ->
107+
h.toLoc :: Nil))
108+
Term.Error
92109
case id @ Ident("this") =>
93110
ctx.getOuter match
94111
case S(sym) =>
@@ -425,6 +442,17 @@ extends Importer:
425442
case (tree @ LetLike(`let`, lhs, S(rhs), N)) :: sts =>
426443
raise(ErrorReport(msg"Unsupported let binding shape" -> tree.toLoc :: Nil))
427444
go(sts, Term.Error :: acc)
445+
case (hd @ Handle(id: Ident, cls: Ident, Block(sts_), N)) :: sts =>
446+
val sym =
447+
fieldOrVarSym(LetBind, id)
448+
log(s"Processing `handle` statement $id (${sym}) ${ctx.outer}")
449+
val newAcc = Term.Handle(sym, term(cls), ObjBody(block(sts_)._1)) :: acc
450+
ctx.copy(locals = ctx.locals + (id.name -> sym)) givenIn:
451+
go(sts, newAcc)
452+
case (tree @ Handle(_, _, _, N)) :: sts =>
453+
raise(ErrorReport(msg"Unsupported handle binding shape" -> tree.toLoc :: Nil))
454+
go(sts, Term.Error :: acc)
455+
428456
case Def(lhs, rhs) :: sts =>
429457
lhs match
430458
case id: Ident =>

hkmc2/shared/src/main/scala/hkmc2/semantics/Term.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ enum Term extends Statement:
3535
case Deref(ref: Term)
3636
case Ret(result: Term)
3737
case Try(body: Term, finallyDo: Term)
38+
case Handle(lhs: LocalSymbol, rhs: Term, defs: ObjBody)
3839

3940
var symbol: Opt[Symbol] = N
4041

@@ -122,6 +123,7 @@ sealed trait Statement extends AutoLocated:
122123
td.rhs.toList
123124
case Import(sym, pth) => Nil
124125
case Try(body, finallyDo) => body :: finallyDo :: Nil
126+
case Handle(lhs, rhs, defs) => rhs :: defs._1 :: Nil
125127
case This(_) => Nil
126128
case Neg(e) => e :: Nil
127129

@@ -171,6 +173,7 @@ sealed trait Statement extends AutoLocated:
171173
case Asc(term, ty) => s"${term.toString}: ${ty.toString}"
172174
case LetDecl(sym) => s"let ${sym}"
173175
case DefineVar(sym, rhs) => s"${sym} = ${rhs.showDbg}"
176+
case Handle(lhs, rhs, defs) => s"handle ${lhs} = ${rhs} ${defs}"
174177
case Region(name, body) => s"region ${name.nme} in ${body.showDbg}"
175178
case RegRef(reg, value) => s"(${reg.showDbg}).ref ${value.showDbg}"
176179
case Assgn(lhs, rhs) => s"${lhs.showDbg} := ${rhs.showDbg}"

hkmc2/shared/src/main/scala/hkmc2/syntax/Keyword.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ object Keyword:
7272
val `is` = Keyword("is", nextPrec, curPrec, canStartInfixOnNewLine = false)
7373
val `as` = Keyword("as", nextPrec, curPrec)
7474
val `let` = Keyword("let", nextPrec, curPrec)
75+
val `handle` = Keyword("handle", nextPrec, curPrec)
7576
val `region` = Keyword("region", curPrec, curPrec)
7677
val `rec` = Keyword("rec", N, N)
7778
val `in` = Keyword("in", curPrec, curPrec)

hkmc2/shared/src/main/scala/hkmc2/syntax/ParseRule.scala

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,16 +65,17 @@ object ParseRule:
6565
Expr(body)(k) ::
6666
Blk(body)(k) ::
6767
Nil
68-
69-
val typeDeclTemplate: Alt[Opt[Tree]] =
68+
69+
def typeDeclTemplateThen[A](after: Alt[A]*): Alt[(S[Tree], A)] =
7070
Kw(`with`):
7171
ParseRule("type declaration body")(
7272
Blk(
73-
ParseRule("type declaration block"):
74-
End(())
75-
) { case (res, ()) => S(res) }
73+
ParseRule("type declaration block")(after*)
74+
) { case (res, t) => (S(res), t) }
7675
)
7776

77+
val typeDeclTemplate: Alt[Opt[Tree]] = typeDeclTemplateThen(End(())).map((res, _) => res)
78+
7879
/*
7980
def termDefBody(k: TermDefKind): ParseRule[Tree] =
8081
ParseRule(s"'${k.str}' binding keyword")(
@@ -138,8 +139,8 @@ object ParseRule:
138139
ParseRule(s"'${kw.name}' binding right-hand side")(
139140
Kw(`in`):
140141
ParseRule(s"'${kw.name}' binding `in` clause")(
141-
exprOrBlk(ParseRule(s"'${kw.name}' binding body")(End(())))((body, _: Unit) => S(body))
142-
*),
142+
exprOrBlk(ParseRule(s"'${kw.name}' binding body")(End(())))((body, _: Unit) => S(body))*
143+
),
143144
End(N)
144145
)
145146
) { (rhs, body) => (S(rhs), body) }*
@@ -189,6 +190,25 @@ object ParseRule:
189190
val prefixRules: ParseRule[Tree] = ParseRule("start of statement", omitAltsStr = true)(
190191
letLike(`let`),
191192
letLike(`set`),
193+
194+
Kw(`handle`):
195+
ParseRule("'handle' binding keyword"):
196+
Expr(
197+
ParseRule("'handle' binding head"):
198+
Kw(`=`):
199+
ParseRule("'handle' binding equals sign"):
200+
Expr(
201+
ParseRule("'handle' binding class name"):
202+
typeDeclTemplateThen(
203+
Kw(`in`):
204+
ParseRule(s"'handle' binding `in` clause")(
205+
exprOrBlk(ParseRule(s"'handle' binding body")(End(())))((body, _: Unit) => S(body))*
206+
),
207+
End(None)
208+
)
209+
) { case (rhs, (S(defs), body)) => (rhs, defs, body) }
210+
) { case (lhs, (rhs, defs, body))=> Handle(lhs, rhs, defs, body) }
211+
,
192212
Kw(`new`):
193213
ParseRule("`new` keyword"):
194214
Expr(ParseRule("`new` expression")(End(())))((body, _: Unit) => New(body))

hkmc2/shared/src/main/scala/hkmc2/syntax/Tree.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum Tree extends AutoLocated:
4949
case Block(stmts: Ls[Tree])
5050
case OpBlock(items: Ls[Tree -> Tree])
5151
case LetLike(kw: Keyword.letLike, lhs: Tree, rhs: Opt[Tree], body: Opt[Tree])
52+
case Handle(lhs: Tree, cls: Tree, defs: Tree, body: Opt[Tree])
5253
case Def(lhs: Tree, rhs: Tree)
5354
case TermDef(k: TermDefKind, head: Tree, rhs: Opt[Tree]) extends Tree with TermDefImpl
5455
case TypeDef(k: TypeDefKind, head: Tree, extension: Opt[Tree], body: Opt[Tree]) extends Tree with TypeDefImpl
@@ -77,6 +78,9 @@ enum Tree extends AutoLocated:
7778
case OpBlock(items) => items.flatMap:
7879
case (op, body) => op :: body :: Nil
7980
case LetLike(kw, lhs, rhs, body) => lhs :: Nil ++ rhs ++ body
81+
case Handle(lhs, rhs, defs, body) => body match
82+
case Some(value) => lhs :: rhs :: defs :: value :: Nil
83+
case None => lhs :: rhs :: defs :: Nil
8084
case TypeDef(k, head, extension, body) =>
8185
head :: extension.toList ::: body.toList
8286
case Modified(_, _, body) => Ls(body)
@@ -129,6 +133,7 @@ enum Tree extends AutoLocated:
129133
case Region(name, body) => "region"
130134
case RegRef(reg, value) => "region reference"
131135
case Effectful(eff, body) => "effectful"
136+
case Handle(_, _, _, _) => "handle"
132137

133138
def showDbg: Str = toString // TODO
134139

@@ -171,6 +176,7 @@ sealed abstract class Val(str: Str, desc: Str) extends ValLike(str, desc)
171176
case object ImmutVal extends Val("val", "value")
172177
case object MutVal extends Val("mut val", "mutable value")
173178
case object LetBind extends ValLike("let", "let binding")
179+
case object Handler extends TermDefKind("handler", "handler binding")
174180
case object ParamBind extends ValLike("", "parameter")
175181
case object Fun extends TermDefKind("fun", "function")
176182
sealed abstract class TypeDefKind(desc: Str) extends DeclKind(desc)

hkmc2/shared/src/test/mlscript/codegen/Bindings.mls

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ let x += 1 = 0 in x
7373

7474
:e
7575
(let x = 1) + 1
76-
//│ ╔══[ERROR] Expected a right-hand side for let bindings in expression position
76+
//│ ╔══[ERROR] Expected a body for let bindings in expression position
7777
//│ ║ l.75: (let x = 1) + 1
7878
//│ ╙── ^^^^^
7979
//│ = NaN
8080

8181
:e
8282
(let f(x) = x) + 1
83-
//│ ╔══[ERROR] Expected a right-hand side for let bindings in expression position
83+
//│ ╔══[ERROR] Expected a body for let bindings in expression position
8484
//│ ║ l.82: (let f(x) = x) + 1
8585
//│ ╙── ^^^^^^^^
8686
//│ = NaN
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
2+
:pe
3+
handle
4+
//│ ╔══[PARSE ERROR] Expected expression after 'handle' binding keyword; found end of input instead
5+
//│ ║ l.3: handle
6+
//│ ╙── ^
7+
8+
:pe
9+
handle h
10+
//│ ╔══[PARSE ERROR] Expected '=' keyword after 'handle' binding head; found end of input instead
11+
//│ ║ l.9: handle h
12+
//│ ╙── ^
13+
14+
:pe
15+
handle h = Eff
16+
//│ ╔══[PARSE ERROR] Expected 'with' keyword after 'handle' binding class name; found end of input instead
17+
//│ ║ l.15: handle h = Eff
18+
//│ ╙── ^
19+
20+
:parseOnly
21+
handle h = Eff with
22+
fun f(r) = r(0)
23+
fun g(a, r) = r(1)
24+
//│ Parsed:
25+
//│ Handle(Ident(h),Ident(Eff),Block(List(TermDef(Fun,App(Ident(f),Tup(List(Ident(r)))),Some(App(Ident(r),Tup(List(IntLit(0)))))), TermDef(Fun,App(Ident(g),Tup(List(Ident(a), Ident(r)))),Some(App(Ident(r),Tup(List(IntLit(1)))))))),None)
26+
27+
28+
:e
29+
fun foo(x) = 1
30+
handle 1 = 1 with
31+
fun f(r) = r(0)
32+
in
33+
foo(h)
34+
//│ ╔══[ERROR] Unsupported handle binding shape
35+
//│ ║ l.30: handle 1 = 1 with
36+
//│ ║ ^^^^^^^^^^
37+
//│ ║ l.31: fun f(r) = r(0)
38+
//│ ╙── ^^^^^^^^^^^^^^^^^
39+
//│ ╔══[ERROR] Name not found: h
40+
//│ ║ l.33: foo(h)
41+
//│ ╙── ^
42+
43+
class Eff
44+
fun foo(h) = 0
45+
handle h = Eff with
46+
fun f(r) = r(0)
47+
in
48+
foo(h)
49+
50+
class Eff
51+
fun foo(h) = 0
52+
handle h = Eff with
53+
fun f(r) = r(0)
54+
fun g(a, r) = r(1)
55+
foo(h)
56+
57+
:e
58+
(
59+
handle h = Eff with
60+
fun f(r) = r(0)
61+
fun g(a, r) = r(1)
62+
) + 1
63+
//│ ╔══[ERROR] Expected a body for handle bindings in expression position
64+
//│ ║ l.59: handle h = Eff with
65+
//│ ║ ^^^^^^^^^^^^
66+
//│ ║ l.60: fun f(r) = r(0)
67+
//│ ║ ^^^^^^^^^^^^^^^^^^^
68+
//│ ║ l.61: fun g(a, r) = r(1)
69+
//│ ╙── ^^^^^^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)