Skip to content

Commit

Permalink
Add way to refer to Predef symbol in Elab. by declaring it in Prelude
Browse files Browse the repository at this point in the history
TODO We have not yet properly implemented declarations:
their implementations currently create new symbols.
  • Loading branch information
LPTK committed Nov 30, 2024
1 parent 0cc3189 commit 9b359cd
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 8 deletions.
12 changes: 9 additions & 3 deletions hkmc2/shared/src/main/scala/hkmc2/semantics/Elaborator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
18 changes: 14 additions & 4 deletions hkmc2/shared/src/test/mlscript-compile/Predef.mjs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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) {
Expand Down
7 changes: 6 additions & 1 deletion hkmc2/shared/src/test/mlscript-compile/Predef.mls
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -29,3 +31,6 @@ fun checkArgs(functionName, expected, isUB, got) =
// + " arguments but got " + got)
else ()

class Test with
val y = 1

17 changes: 17 additions & 0 deletions hkmc2/shared/src/test/mlscript/basics/PredefTest.mls
Original file line number Diff line number Diff line change
@@ -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'


5 changes: 5 additions & 0 deletions hkmc2/shared/src/test/mlscript/decls/Prelude.mls
Original file line number Diff line number Diff line change
Expand Up @@ -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) -> ()
Expand Down

0 comments on commit 9b359cd

Please sign in to comment.