diff --git a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala index ba4d6516f..2146cca04 100644 --- a/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala +++ b/hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala @@ -64,14 +64,20 @@ object Elaborator: def getBuiltin(nme: Str): Opt[Ctx.Elem] = parent.filter(_.parent.nonEmpty).fold(env.get(nme))(_.getBuiltin(nme)) object Builtins: - private def assumeBuiltinCls(nme: Str): ClassSymbol = + private def assumeBuiltin(nme: Str): Symbol = getBuiltin(nme) - .getOrElse(throw new NoSuchElementException(s"builtin $nme ${env.keySet} $parent")) + .getOrElse(throw new NoSuchElementException(s"builtin $nme not in ${parent.map(_.env.keySet)}")) .symbol.getOrElse(throw new NoSuchElementException(s"builtin symbol $nme")) - .asCls.getOrElse(throw new NoSuchElementException(s"builtin class symbol $nme")) + private def assumeBuiltinCls(nme: Str): ClassSymbol = + assumeBuiltin(nme).asCls.getOrElse(throw new NoSuchElementException( + s"builtin class symbol $nme")) + private def assumeBuiltinMod(nme: Str): ModuleSymbol = + assumeBuiltin(nme).asMod.getOrElse(throw new NoSuchElementException( + s"builtin module symbol $nme")) val Int = assumeBuiltinCls("Int") val Num = assumeBuiltinCls("Num") val Str = assumeBuiltinCls("Str") + val Predef = assumeBuiltinMod("Predef") object Ctx: abstract class Elem: diff --git a/hkmc2/shared/src/test/mlscript-compile/Predef.mjs b/hkmc2/shared/src/test/mlscript-compile/Predef.mjs index c0380265e..41058291b 100644 --- a/hkmc2/shared/src/test/mlscript-compile/Predef.mjs +++ b/hkmc2/shared/src/test/mlscript-compile/Predef.mjs @@ -1,6 +1,11 @@ const Predef$class = class Predef { constructor() { - + this.Test = class Test { + constructor() { + this.y = 1; + } + toString() { return "Test"; } + }; } id(x) { return x; @@ -15,9 +20,14 @@ const Predef$class = class Predef { pipe(x2, f) { return f(x2); } - call(receiver, f1) { - return (arg) => { - return f1.call(receiver, arg); + apply(receiver, f1) { + return (...args) => { + return f1(receiver, ...args); + }; + } + call(receiver1, f2) { + return (...args) => { + return f2.call(receiver1, ...args); }; } print(x3) { diff --git a/hkmc2/shared/src/test/mlscript-compile/Predef.mls b/hkmc2/shared/src/test/mlscript-compile/Predef.mls index 9dfce582c..5bdfd51fa 100644 --- a/hkmc2/shared/src/test/mlscript-compile/Predef.mls +++ b/hkmc2/shared/src/test/mlscript-compile/Predef.mls @@ -7,7 +7,9 @@ fun not(x) = x is false fun (|>) pipe(x, f) = f(x) -fun (|>.) call(receiver, f)(arg) = f.call(receiver, arg) +fun (.) apply(receiver, f)(...args) = f(receiver, ...args) + +fun (|>.) call(receiver, f)(...args) = f.call(receiver, ...args) fun print(x) = console.log(String(x)) @@ -29,3 +31,6 @@ fun checkArgs(functionName, expected, isUB, got) = // + " arguments but got " + got) else () +class Test with + val y = 1 + diff --git a/hkmc2/shared/src/test/mlscript/basics/PredefTest.mls b/hkmc2/shared/src/test/mlscript/basics/PredefTest.mls new file mode 100644 index 000000000..cfa319229 --- /dev/null +++ b/hkmc2/shared/src/test/mlscript/basics/PredefTest.mls @@ -0,0 +1,17 @@ +:js + + +Test === Predef.Test +//│ = true + +Predef.Test === globalThis.Predef.Test +//│ = true + +(new Predef.Test).y +//│ = 1 + +:re +(new Predef.Test).x +//│ ═══[RUNTIME ERROR] Error: Access to required field 'x' yielded 'undefined' + + diff --git a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls index 9f915a9d8..7f1fe45bf 100644 --- a/hkmc2/shared/src/test/mlscript/decls/Prelude.mls +++ b/hkmc2/shared/src/test/mlscript/decls/Prelude.mls @@ -20,6 +20,11 @@ declare val process declare val fs +declare module Predef with + class Test with + val x = 0 + + // TODO: rm declare fun log: (Any) -> ()