Skip to content

Commit 17bbfb6

Browse files
AnsonYeungLPTK
andauthored
Add additional test cases (hkust-taco#296)
Co-authored-by: Lionel Parreaux <lionel.parreaux@gmail.com>
1 parent 8acdf7b commit 17bbfb6

30 files changed

+433
-186
lines changed

hkmc2/shared/src/main/scala/hkmc2/codegen/Lifter.scala

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,12 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise):
613613
case Assign(t: TermSymbol, rhs, rest) if t.owner.isDefined =>
614614
ctx.getIsymPath(t.owner.get) match
615615
case Some(value) if !belongsToCtor(t.owner.get) =>
616+
if (t.k is syntax.LetBind) && !t.owner.forall(_.isInstanceOf[semantics.TopLevelSymbol]) then
617+
// TODO: improve the error message
618+
raise(ErrorReport(
619+
msg"Uses of private fields cannot yet be lifted." -> N :: Nil,
620+
N, Diagnostic.Source.Compilation
621+
))
616622
AssignField(value.asPath, t.id, applyResult(rhs), applyBlock(rest))(N)
617623
case _ => super.applyBlock(rewritten)
618624

@@ -623,6 +629,12 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise):
623629
case None => super.applyBlock(rewritten)
624630
case Some(value) => Assign(value, applyResult(rhs), applyBlock(rest))
625631

632+
case Define(d: ValDefn, rest: Block) if d.owner.isDefined =>
633+
ctx.getIsymPath(d.owner.get) match
634+
case Some(value) if !belongsToCtor(d.owner.get) =>
635+
AssignField(value.asPath, Tree.Ident(d.sym.nme), applyResult(d.rhs), applyBlock(rest))(S(d.sym))
636+
case _ => super.applyBlock(rewritten)
637+
626638
case Define(d: Defn, rest: Block) => ctx.modLocals.get(d.sym) match
627639
case Some(sym) if !ctx.ignored(d.sym) => ctx.getBmsReqdInfo(d.sym) match
628640
case Some(_) =>
@@ -650,7 +662,14 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise):
650662
case _ => super.applyPath(p)
651663
case Value.Ref(t: TermSymbol) if t.owner.isDefined =>
652664
ctx.getIsymPath(t.owner.get) match
653-
case Some(value) if !belongsToCtor(t.owner.get) => Select(value.asPath, t.id)(N)
665+
case Some(value) if !belongsToCtor(t.owner.get) =>
666+
if (t.k is syntax.LetBind) && !t.owner.forall(_.isInstanceOf[semantics.TopLevelSymbol]) then
667+
// TODO: improve the error message
668+
raise(ErrorReport(
669+
msg"Uses of private fields cannot yet be lifted." -> N :: Nil,
670+
N, Diagnostic.Source.Compilation
671+
))
672+
Select(value.asPath, t.id)(N)
654673
case _ => super.applyPath(p)
655674

656675
// Rewrites this.className.class to reference the top-level definition
@@ -885,7 +904,7 @@ class Lifter(handlerPaths: Opt[HandlerPaths])(using State, Raise):
885904
val newCtx_ = ctxx
886905
.addLocalPaths(nestedClsPaths)
887906
.addLocalPaths(getVars(c).map(s => s -> s).toMap)
888-
.addIgnoredBmsPaths(ctorIgnored.map(d => d.sym -> Select(c.isym.asPath, Tree.Ident(d.sym.nme))(S(d.sym))).toMap)
907+
.addIgnoredBmsPaths(ctorIgnored.map(d => d.sym -> d.sym.asPath).toMap)
889908

890909
val newCtx = c.k match
891910
case syntax.Mod if !ctx.ignored(c.sym) => newCtx_

hkmc2/shared/src/main/scala/hkmc2/codegen/js/JSBuilder.scala

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,10 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
6262
case ts: semantics.TermSymbol =>
6363
ts.owner match
6464
case S(owner) =>
65-
doc"${getVar(owner)}.${
65+
doc"${getVar(owner)}${
6666
if (ts.k is syntax.LetBind) && !owner.isInstanceOf[semantics.TopLevelSymbol]
67-
then "#" + owner.privatesScope.lookup_!(ts)
68-
else ts.id.name
67+
then ".#" + owner.privatesScope.lookup_!(ts)
68+
else fieldSelect(ts.id.name)
6969
}"
7070
case N => summon[Scope].lookup_!(ts)
7171
case ts: semantics.InnerSymbol =>
@@ -86,6 +86,12 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
8686
case _: Value.Lam => doc"(${result(r)})"
8787
case _ => result(r)
8888

89+
def fieldSelect(s: Str): Document =
90+
if JSBuilder.isValidFieldName(s) then doc".$s"
91+
else s.toIntOption match
92+
case S(index) => s"[$index]"
93+
case N => s"[${JSBuilder.makeStringLiteral(s)}]"
94+
8995
def result(r: Result)(using Raise, Scope): Document = r match
9096
case Value.This(sym) => summon[Scope].findThis_!(sym)
9197
case Value.Lit(Tree.StrLit(value)) => JSBuilder.makeStringLiteral(value)
@@ -161,7 +167,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
161167
case Assign(l, r, rst) =>
162168
doc" # ${getVar(l)} = ${result(r)};${returningTerm(rst, endSemi)}"
163169
case AssignField(p, n, r, rst) =>
164-
doc" # ${result(p)}.${n.name} = ${result(r)};${returningTerm(rst, endSemi)}"
170+
doc" # ${result(p)}${fieldSelect(n.name)} = ${result(r)};${returningTerm(rst, endSemi)}"
165171
case AssignDynField(p, f, ai, r, rst) =>
166172
doc" # ${result(p)}[${result(f)}] = ${result(r)};${returningTerm(rst, endSemi)}"
167173
case Define(defn, rst) =>
@@ -176,7 +182,7 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
176182
case N =>
177183
doc"${getVar(sym)} = ${result(p)};${returningTerm(rst, endSemi)}"
178184
case S(owner) =>
179-
doc"${mkThis(owner)}.${sym.nme} = ${result(p)};${returningTerm(rst, endSemi)}"
185+
doc"${mkThis(owner)}${fieldSelect(sym.nme)} = ${result(p)};${returningTerm(rst, endSemi)}"
180186
case defn: (FunDefn | ClsLikeDefn) =>
181187
val outerScope = scope
182188
val (thisProxy, res) = scope.nestRebindThis(
@@ -218,19 +224,28 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
218224
.mkDocument(doc"")
219225
val preCtorCode = ctorAuxParams.flatMap(ps => ps).foldLeft(body(preCtor, endSemi = true)):
220226
case (acc, (sym, nme)) =>
221-
doc"$acc # this.${sym.name} = $nme;"
222-
val ctorCode = doc"$preCtorCode${body(ctor, endSemi = false)}"
227+
doc"$acc # this${fieldSelect(sym.name)} = $nme;"
228+
val ctorCode = doc"$preCtorCode${body(ctor, endSemi = auxParams.nonEmpty)}"
223229

224-
val ctorBod = if auxParams.isEmpty then
225-
doc"${braced(ctorCode)}"
230+
val ctorAux = if auxParams.isEmpty then
231+
ctorCode
226232
else
227233
val pss = ctorAuxParams.map(_.map(_._2))
228234
val newCtorCode = doc"$ctorCode # return this;"
229235
val ctorBraced = doc"${ braced(newCtorCode) }"
230236
val funBod = pss.foldRight(ctorBraced):
231237
case (psDoc, doc) => doc"(${psDoc.mkDocument(", ")}) => $doc"
232238

233-
doc"${ braced(doc" # return $funBod") }"
239+
doc" # return $funBod"
240+
241+
val ctorBod = if isModule then
242+
ownr match
243+
case S(owner) =>
244+
braced(doc" # ${result(Value.Ref(owner))}.${sym.nme} = ${getVar(isym)};$ctorCode")
245+
case N =>
246+
braced(doc" # ${getVar(sym)} = ${getVar(isym)};$ctorCode")
247+
else
248+
braced(ctorAux)
234249

235250
val ctorOrStatic = if isModule
236251
then doc"static"
@@ -271,10 +286,10 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
271286
else doc""" # ${mtdPrefix}toString() { return "${sym.nme}${
272287
if paramsOpt.isEmpty then doc"""""""
273288
else doc"""(" + ${
274-
ctorFields.headOption.fold("\"\"")("globalThis.Predef.render(this." + _._1.name + ")")
289+
ctorFields.headOption.fold("\"\"")(f => "globalThis.Predef.render(this" + fieldSelect(f._1.name) + ")")
275290
}${
276-
ctorFields.tailOption.fold("")(_.map(
277-
""" + ", " + globalThis.Predef.render(this.""" + _._1.name + ")").mkString)
291+
ctorFields.tailOption.fold("")(_.map(f =>
292+
""" + ", " + globalThis.Predef.render(this""" + fieldSelect(f._1.name) + ")").mkString)
278293
} + ")""""
279294
}; }"""
280295
} #} # }"
@@ -285,13 +300,13 @@ class JSBuilder(using TL, State, Ctx) extends CodeBuilder:
285300
assert((kind is syntax.Pat) || paramsOpt.isEmpty)
286301
// doc"${mkThis(owner)}.${sym.nme} = new ${clsJS}"
287302
if isModule
288-
then doc"${mkThis(owner)}.${sym.nme} = ${clsJS};"
303+
then doc"(${clsJS});"
289304
else doc"const $clsTmp = ${clsJS}; # ${mkThis(owner)}.${sym.nme} = new ${clsTmp
290305
}; # ${mkThis(owner)}.${sym.nme}.class = $clsTmp;"
291306
case N =>
292307
val v = getVar(sym)
293308
if isModule
294-
then doc"${v} = ${clsJS};"
309+
then doc"(${clsJS});"
295310
else doc"const $clsTmp = ${clsJS}; ${v} = new ${clsTmp
296311
}; # ${v}.class = $clsTmp;"
297312
else

hkmc2/shared/src/test/mlscript-compile/Example.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@ let privFun, Example1;
44
privFun = function privFun() {
55
return "hi"
66
};
7-
Example1 = class Example {
8-
static {}
7+
(class Example {
8+
static {
9+
Example1 = Example;
10+
}
911
static get pubFun() {
1012
let tmp;
1113
tmp = privFun();
@@ -29,5 +31,5 @@ Example1 = class Example {
2931
}
3032
}
3133
static toString() { return "Example"; }
32-
};
34+
});
3335
let Example = Example1; export default Example;

hkmc2/shared/src/test/mlscript-compile/Iter.mjs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ Iterator1.class = class Iterator {
2424
}
2525
toString() { return "Iterator(" + globalThis.Predef.render(this.next) + ")"; }
2626
};
27-
Result1 = class Result {
27+
(class Result {
2828
static {
29+
Result1 = Result;
2930
this.Next = function Next(value1) {
3031
return new Next.class(value1);
3132
};
@@ -46,9 +47,11 @@ Result1 = class Result {
4647
this.Done.class = Done$class;
4748
}
4849
static toString() { return "Result"; }
49-
};
50-
Iter1 = class Iter {
51-
static {}
50+
});
51+
(class Iter {
52+
static {
53+
Iter1 = Iter;
54+
}
5255
static getIterator(something) {
5356
let test, prototype, tmp, tmp1;
5457
test = something[globalThis.Symbol.iterator];
@@ -474,5 +477,5 @@ Iter1 = class Iter {
474477
return Iter.rightFolded(xs12, Stack.Nil, Stack.Cons)
475478
}
476479
static toString() { return "Iter"; }
477-
};
480+
});
478481
let Iter = Iter1; export default Iter;

hkmc2/shared/src/test/mlscript-compile/Option.mjs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import runtime from "./Runtime.mjs";
22
import Predef from "./Predef.mjs";
33
let Option1;
4-
Option1 = class Option {
4+
(class Option {
55
static {
6+
Option1 = Option;
67
this.Some = function Some(value1) {
78
return new Some.class(value1);
89
};
@@ -28,8 +29,10 @@ Option1 = class Option {
2829
}
2930
toString() { return "Both(" + globalThis.Predef.render(this.fst) + ", " + globalThis.Predef.render(this.snd) + ")"; }
3031
};
31-
this.unsafe = class unsafe {
32-
static {}
32+
(class unsafe {
33+
static {
34+
Option.unsafe = unsafe;
35+
}
3336
static get(opt) {
3437
let param0, value;
3538
if (opt instanceof Option.Some.class) {
@@ -43,7 +46,7 @@ Option1 = class Option {
4346
}
4447
}
4548
static toString() { return "unsafe"; }
46-
};
49+
});
4750
}
4851
static isDefined(x) {
4952
if (x instanceof Option.Some.class) {
@@ -70,5 +73,5 @@ Option1 = class Option {
7073
}
7174
}
7275
static toString() { return "Option"; }
73-
};
76+
});
7477
let Option = Option1; export default Option;

hkmc2/shared/src/test/mlscript-compile/Predef.mjs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import runtime from "./Runtime.mjs";
22
import Runtime from "./Runtime.mjs";
33
import Rendering from "./Rendering.mjs";
44
let Predef1;
5-
Predef1 = class Predef {
5+
(class Predef {
66
static {
7+
Predef1 = Predef;
78
this.pass1 = Rendering.pass1;
89
this.pass2 = Rendering.pass2;
910
this.pass3 = Rendering.pass3;
@@ -14,8 +15,9 @@ Predef1 = class Predef {
1415
this.render = Rendering.render;
1516
this.assert = globalThis.console.assert;
1617
this.foldl = Predef.fold;
17-
this.TraceLogger = class TraceLogger {
18+
(class TraceLogger {
1819
static {
20+
Predef.TraceLogger = TraceLogger;
1921
this.enabled = false;
2022
this.indentLvl = 0;
2123
}
@@ -56,7 +58,7 @@ Predef1 = class Predef {
5658
}
5759
}
5860
static toString() { return "TraceLogger"; }
59-
};
61+
});
6062
this.Test = class Test {
6163
constructor() {
6264
let tmp;
@@ -259,5 +261,5 @@ Predef1 = class Predef {
259261
return Runtime.mkEffect(Runtime.FatalEffect, null)
260262
}
261263
static toString() { return "Predef"; }
262-
};
264+
});
263265
let Predef = Predef1; export default Predef;

hkmc2/shared/src/test/mlscript-compile/Rendering.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import runtime from "./Runtime.mjs";
22
let Rendering1;
3-
Rendering1 = class Rendering {
4-
static {}
3+
(class Rendering {
4+
static {
5+
Rendering1 = Rendering;
6+
}
57
static pass1(f) {
68
return (...xs) => {
79
return runtime.safeCall(f(xs[0]))
@@ -233,5 +235,5 @@ Rendering1 = class Rendering {
233235
}
234236
}
235237
static toString() { return "Rendering"; }
236-
};
238+
});
237239
let Rendering = Rendering1; export default Rendering;

hkmc2/shared/src/test/mlscript-compile/Runtime.mjs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ import runtime from "./Runtime.mjs";
22
import RuntimeJS from "./RuntimeJS.mjs";
33
import Rendering from "./Rendering.mjs";
44
let Runtime1;
5-
Runtime1 = class Runtime {
5+
(class Runtime {
66
static {
7+
Runtime1 = Runtime;
78
const Unit$class = class Unit {
89
constructor() {}
910
toString() {
@@ -696,5 +697,5 @@ Runtime1 = class Runtime {
696697
return result
697698
}
698699
static toString() { return "Runtime"; }
699-
};
700+
});
700701
let Runtime = Runtime1; export default Runtime;

hkmc2/shared/src/test/mlscript-compile/Stack.mjs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import runtime from "./Runtime.mjs";
22
import Predef from "./Predef.mjs";
33
let Stack1;
4-
Stack1 = class Stack {
4+
(class Stack {
55
static {
6+
Stack1 = Stack;
67
this.Cons = function Cons(head1, tail1) {
78
return new Cons.class(head1, tail1);
89
};
@@ -206,5 +207,5 @@ Stack1 = class Stack {
206207
}
207208
}
208209
static toString() { return "Stack"; }
209-
};
210+
});
210211
let Stack = Stack1; export default Stack;

hkmc2/shared/src/test/mlscript-compile/Str.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import runtime from "./Runtime.mjs";
22
let Str1;
3-
Str1 = class Str {
4-
static {}
3+
(class Str {
4+
static {
5+
Str1 = Str;
6+
}
57
static concat2(a, b) {
68
return a + b
79
}
@@ -21,5 +23,5 @@ Str1 = class Str {
2123
}
2224
}
2325
static toString() { return "Str"; }
24-
};
26+
});
2527
let Str = Str1; export default Str;

hkmc2/shared/src/test/mlscript-compile/XML.mjs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ StyleAttributeValue1.class = class StyleAttributeValue {
1212
}
1313
toString() { return "StyleAttributeValue(" + "" + ")"; }
1414
};
15-
XML1 = class XML {
16-
static {}
15+
(class XML {
16+
static {
17+
XML1 = XML;
18+
}
1719
static serializeValue(value) {
1820
let param0, rules, tmp, tmp1, tmp2, lambda;
1921
if (typeof value === 'string') {
@@ -106,5 +108,5 @@ XML1 = class XML {
106108
}
107109
}
108110
static toString() { return "XML"; }
109-
};
111+
});
110112
let XML = XML1; export default XML;

0 commit comments

Comments
 (0)