Skip to content

Commit c3d6d37

Browse files
authored
Return null by default and remove unnecessary ?? nulls (hkust-taco#248)
* use null instead of undefined * determine if is mls fun in lowering using the trees associated with blockmembersymbol * make `?? null` default behavior instead of being related to sanity check
1 parent dbc6bcb commit c3d6d37

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+286
-293
lines changed

hkmc2/jvm/src/test/scala/hkmc2/JSBackendDiffMaker.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import utils.*
77

88
import semantics.*
99
import codegen.*
10-
import codegen.js.{JSBuilder, JSBuilderArgNumSanityChecks, JSBuilderSelSanityChecks}
10+
import codegen.js.{JSBuilder, JSBuilderArgNumSanityChecks}
1111
import document.*
1212
import codegen.Block
1313
import codegen.js.Scope
@@ -57,7 +57,6 @@ abstract class JSBackendDiffMaker extends MLsDiffMaker:
5757
given Elaborator.Ctx = curCtx
5858
val jsb = new JSBuilder
5959
with JSBuilderArgNumSanityChecks(noSanityCheck.isUnset)
60-
with JSBuilderSelSanityChecks(noSanityCheck.isUnset)
6160
val le = low.program(blk)
6261
if showLoweredTree.isSet then
6362
output(s"Lowered:")

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ sealed abstract class Result
121121
// type Local = LocalSymbol
122122
type Local = Symbol
123123

124-
case class Call(fun: Path, args: Ls[Arg]) extends Result
124+
case class Call(fun: Path, args: Ls[Arg])(val isMlsFun: Bool) extends Result
125125

126126
case class Instantiate(cls: Path, args: Ls[Path]) extends Result
127127

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

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ class Lowering(using TL, Raise, Elaborator.State):
6868
case st.Ref(sym) =>
6969
k(subst(Value.Ref(sym)))
7070
case st.App(f, arg) =>
71+
val isMlsFun = f.symbol.fold(f.isInstanceOf[st.Lam]):
72+
case _: sem.BuiltinSymbol => true
73+
case sym: sem.BlockMemberSymbol =>
74+
sym.trmImplTree.fold(sym.clsTree.isDefined)(_.k is syntax.Fun)
75+
case _ => false
7176
arg match
7277
case Tup(fs) =>
7378
val as = fs.map:
@@ -79,7 +84,7 @@ class Lowering(using TL, Raise, Elaborator.State):
7984
val l = new TempSymbol(S(t))
8085
subTerm(f): fr =>
8186
def rec(as: Ls[Bool -> st], asr: Ls[Arg]): Block = as match
82-
case Nil => k(Call(fr, asr.reverse))
87+
case Nil => k(Call(fr, asr.reverse)(isMlsFun))
8388
case (spd, a) :: as =>
8489
subTerm(a): ar =>
8590
rec(as, Arg(spd, ar) :: asr)
@@ -348,7 +353,7 @@ trait LoweringSelSanityChecks
348353
val split = Split.Cons(
349354
Branch(
350355
selRes.ref(),
351-
Pattern.Lit(syntax.Tree.UnitLit(true)),
356+
Pattern.Lit(syntax.Tree.UnitLit(false)),
352357
Split.Else(
353358
Term.Throw(Term.New(SynthSel(State.globalThisSymbol.ref(), Tree.Ident("Error"))(N),
354359
Term.Lit(syntax.Tree.StrLit(s"Access to required field '${nme.name}' yielded 'undefined'")) :: Nil)
@@ -375,6 +380,9 @@ trait LoweringTraceLog
375380
stmts.foldRight(rest):
376381
case ((sym, res), acc) => Assign(sym, res, acc)
377382

383+
private def call(fn: Path, args: Ls[Arg]): Call =
384+
Call(fn, args)(true)
385+
378386
extension (k: Block => Block)
379387
def |>: (b: Block): Block = k(b)
380388

@@ -415,26 +423,26 @@ trait LoweringTraceLog
415423
else Arg(false, Value.Ref(s)) :: Arg(false, Value.Lit(Tree.StrLit(", "))) :: acc
416424

417425
assignStmts(psInspectedSyms.map: (pInspectedSym, pSym) =>
418-
pInspectedSym -> Call(inspectFn, Arg(false, Value.Ref(pSym)) :: Nil)
426+
pInspectedSym -> call(inspectFn, Arg(false, Value.Ref(pSym)) :: Nil)
419427
*) |>:
420428
assignStmts(
421-
enterMsgSym -> Call(
429+
enterMsgSym -> call(
422430
strConcatFn,
423431
Arg(false, Value.Lit(Tree.StrLit(s"CALL ${name.getOrElse("[arrow function]")}("))) :: psSymArgs
424432
),
425-
TempSymbol(N) -> Call(traceLogFn, Arg(false, Value.Ref(enterMsgSym)) :: Nil),
426-
prevIndentLvlSym -> Call(traceLogIndentFn, Nil)
433+
TempSymbol(N) -> call(traceLogFn, Arg(false, Value.Ref(enterMsgSym)) :: Nil),
434+
prevIndentLvlSym -> call(traceLogIndentFn, Nil)
427435
) |>:
428436
term(bod)(r =>
429437
assignStmts(
430438
resSym -> r,
431-
resInspectedSym -> Call(inspectFn, Arg(false, Value.Ref(resSym)) :: Nil),
432-
retMsgSym -> Call(
439+
resInspectedSym -> call(inspectFn, Arg(false, Value.Ref(resSym)) :: Nil),
440+
retMsgSym -> call(
433441
strConcatFn,
434442
Arg(false, Value.Lit(Tree.StrLit("=> "))) :: Arg(false, Value.Ref(resInspectedSym)) :: Nil
435443
),
436-
TempSymbol(N) -> Call(traceLogResetFn, Arg(false, Value.Ref(prevIndentLvlSym)) :: Nil),
437-
TempSymbol(N) -> Call(traceLogFn, Arg(false, Value.Ref(retMsgSym)) :: Nil)
444+
TempSymbol(N) -> call(traceLogResetFn, Arg(false, Value.Ref(prevIndentLvlSym)) :: Nil),
445+
TempSymbol(N) -> call(traceLogFn, Arg(false, Value.Ref(retMsgSym)) :: Nil)
438446
) |>:
439447
Ret(Value.Ref(resSym))
440448
)

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,12 @@ class JSBuilder(using Elaborator.State, Elaborator.Ctx) extends CodeBuilder:
9393
case Call(Value.Ref(l: BuiltinSymbol), args) =>
9494
err(msg"Illeal arity for builtin symbol '${l.nme}'")
9595

96-
case Call(fun, args) =>
96+
case c @ Call(fun, args) =>
9797
val base = fun match
9898
case _: Value.Lam => doc"(${result(fun)})"
9999
case _ => result(fun)
100-
setupCall(base, args.map(result).mkDocument(", "))
100+
val argsDoc = args.map(result).mkDocument(", ")
101+
if c.isMlsFun then doc"${base}(${argsDoc})" else doc"${base}(${argsDoc}) ?? null"
101102
case Value.Lam(ps, bod) => scope.nest givenIn:
102103
val (params, bodyDoc) = setupFunction(none, ps, bod)
103104
doc"($params) => { #{ # ${
@@ -346,8 +347,6 @@ class JSBuilder(using Elaborator.State, Elaborator.Ctx) extends CodeBuilder:
346347
(paramsList, this.body(body))
347348

348349

349-
def setupCall(bases: Document, args: Document)(using Raise, Scope): Document =
350-
doc"${bases}(${args})"
351350

352351
object JSBuilder:
353352
import scala.util.matching.Regex
@@ -461,12 +460,3 @@ trait JSBuilderArgNumSanityChecks
461460
else
462461
super.setupFunction(name, params, body)
463462

464-
trait JSBuilderSelSanityChecks
465-
(instrument: Bool)(using Elaborator.State)
466-
extends JSBuilder:
467-
468-
override def setupCall(bases: Document, args: Document)(using Raise, Scope): Document =
469-
val basic = super.setupCall(bases, args)
470-
if instrument
471-
then doc"$basic ?? null"
472-
else basic

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,8 @@ class ParseRules(using State):
299299
// modified(`type`),
300300
singleKw(`true`)(BoolLit(true)),
301301
singleKw(`false`)(BoolLit(false)),
302-
singleKw(`undefined`)(UnitLit(true)),
303-
singleKw(`null`)(UnitLit(false)),
302+
singleKw(`undefined`)(UnitLit(false)),
303+
singleKw(`null`)(UnitLit(true)),
304304
singleKw(`this`)(Ident("this")),
305305
standaloneExpr,
306306
)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ sealed trait Literal extends AutoLocated:
2323
case c if c.isControl => f"\\u${c.toInt}%04x"
2424
case c => c.toString
2525
.mkString("\"", "", "\"")
26-
case UnitLit(value) => if value then "undefined" else "null"
26+
case UnitLit(value) => if value then "null" else "undefined"
2727
case BoolLit(value) => value.toString
2828

2929
def describeLit: Str =
@@ -115,7 +115,7 @@ enum Tree extends AutoLocated:
115115
case IntLit(value) => "integer literal"
116116
case DecLit(value) => "decimal literal"
117117
case StrLit(value) => "string literal"
118-
case UnitLit(value) => if value then "undefined" else "null"
118+
case UnitLit(value) => if value then "null" else "undefined"
119119
case BoolLit(value) => s"$value literal"
120120
case Block(stmts) => "block"
121121
case OpBlock(_) => "operator block"

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const Example$class = class Example {
44

55
}
66
funnySlash(f, arg) {
7-
return f(arg);
7+
return f(arg) ?? null;
88
}
99
inc(x) {
1010
return x + 1;
@@ -27,5 +27,5 @@ const Example$class = class Example {
2727
toString() { return "Example"; }
2828
}; const Example = new Example$class;
2929
Example.class = Example$class;
30-
undefined
30+
null
3131
export default Example;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,5 @@ const Option$class = class Option {
4444
toString() { return "Option"; }
4545
}; const Option = new Option$class;
4646
Option.class = Option$class;
47-
undefined
47+
null
4848
export default Option;

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

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,31 @@ const Predef$class = class Predef {
3030
this.indentLvl = tmp;
3131
return prev;
3232
} else {
33-
return undefined;
33+
return null;
3434
}
3535
}
3636
resetIndent(n) {
3737
let scrut;
3838
scrut = this.enabled;
3939
if (scrut) {
4040
this.indentLvl = n;
41-
return undefined;
41+
return null;
4242
} else {
43-
return undefined;
43+
return null;
4444
}
4545
}
4646
log(msg) {
4747
let scrut, tmp, tmp1, tmp2, tmp3, tmp4;
4848
scrut = this.enabled;
4949
if (scrut) {
50-
tmp = "| ".repeat(this.indentLvl);
51-
tmp1 = " ".repeat(this.indentLvl);
50+
tmp = "| ".repeat(this.indentLvl) ?? null;
51+
tmp1 = " ".repeat(this.indentLvl) ?? null;
5252
tmp2 = "\n" + tmp1;
53-
tmp3 = msg.replaceAll("\n", tmp2);
53+
tmp3 = msg.replaceAll("\n", tmp2) ?? null;
5454
tmp4 = tmp + tmp3;
55-
return console.log(tmp4);
55+
return console.log(tmp4) ?? null;
5656
} else {
57-
return undefined;
57+
return null;
5858
}
5959
}
6060
toString() { return "TraceLogger"; }
@@ -79,39 +79,39 @@ const Predef$class = class Predef {
7979
}
8080
}
8181
pipe(x2, f) {
82-
return f(x2);
82+
return f(x2) ?? null;
8383
}
8484
apply(receiver, f1) {
8585
return (...args) => {
86-
return f1(receiver, ...args);
86+
return f1(receiver, ...args) ?? null;
8787
};
8888
}
8989
call(receiver1, f2) {
9090
return (...args) => {
91-
return f2.call(receiver1, ...args);
91+
return f2.call(receiver1, ...args) ?? null;
9292
};
9393
}
9494
print(x3) {
9595
let tmp;
9696
tmp = String(x3);
97-
return console.log(tmp);
97+
return console.log(tmp) ?? null;
9898
}
9999
tupleSlice(xs, i, j) {
100100
let tmp;
101101
tmp = xs.length - j;
102-
return globalThis.Array.prototype.slice.call(xs, i, tmp);
102+
return globalThis.Array.prototype.slice.call(xs, i, tmp) ?? null;
103103
}
104104
tupleGet(xs1, i1) {
105-
return globalThis.Array.prototype.at.call(xs1, i1);
105+
return globalThis.Array.prototype.at.call(xs1, i1) ?? null;
106106
}
107107
stringStartsWith(string, prefix) {
108-
return string.startsWith(prefix);
108+
return string.startsWith(prefix) ?? null;
109109
}
110110
stringGet(string1, i2) {
111-
return string1.at(i2);
111+
return string1.at(i2) ?? null;
112112
}
113113
stringDrop(string2, n) {
114-
return string2.slice(n);
114+
return string2.slice(n) ?? null;
115115
}
116116
checkArgs(functionName, expected, isUB, got) {
117117
let scrut, name, scrut1, tmp, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
@@ -133,13 +133,13 @@ const Predef$class = class Predef {
133133
tmp7 = tmp6 + expected;
134134
tmp8 = tmp7 + " arguments but got ";
135135
tmp9 = tmp8 + got;
136-
throw globalThis.Error(tmp9);
136+
throw globalThis.Error(tmp9) ?? null;
137137
} else {
138-
return undefined;
138+
return null;
139139
}
140140
}
141141
toString() { return "Predef"; }
142142
}; const Predef = new Predef$class;
143143
Predef.class = Predef$class;
144-
undefined
144+
null
145145
export default Predef;

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,5 @@ const Stack$class = class Stack {
2828
toString() { return "Stack"; }
2929
}; const Stack = new Stack$class;
3030
Stack.class = Stack$class;
31-
undefined
31+
null
3232
export default Stack;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ const Str$class = class Str {
66
return a + b;
77
}
88
string(value) {
9-
return globalThis.String(value);
9+
return globalThis.String(value) ?? null;
1010
}
1111
toString() { return "Str"; }
1212
}; const Str = new Str$class;
1313
Str.class = Str$class;
14-
undefined
14+
null
1515
export default Str;

0 commit comments

Comments
 (0)