-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve module method checks #283
base: hkmc2
Are you sure you want to change the base?
Improve module method checks #283
Conversation
case sym: TermSymbol => | ||
// TODO: How can a TermSymbol accept a Declaration | ||
// sym.defn = S(TermDefinition(ctx.outer, Fun, sym, Nil, Nil, sign, N, FlowSymbol(s"‹result of ${sym}›"), TermDefFlags.empty, Nil)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was a little confused about TermSymbol
: it seems like the symbol becomes TermSymbol
if the scope is in the class (i.e., a class's parameter), but other parts of code seem to directly create a BlockMemberSymbol
to represent a term. Also, I found some code seems to related to it, but it was commented with some reason 🤔
So I was not very sure how to deal with this here. I was thinking to change the symbol to BlockMemberSymbol
instead but I don't know if that's appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. This part of the module system is not fully/adequately worked out yet.
A couple of things influencing the current WIP design were:
- class parameters act both as normal parameters and as fields, complicating the handling of parameters
- let bindings in classes are basically private fields
But actually I realized class parameters need a very different handling than that. Consider this:
mlscript/hkmc2/shared/src/test/mlscript/basics/Inheritance.mls
Lines 50 to 68 in 46ae8a7
// FIXME: in super calls, class params should actually be viewed as a `VarSymbol`, not a `TermSymbol` wit owner | |
:sjs | |
class Baz(z) extends Bar(z * 1) with | |
fun baz = this.bar * 2 | |
//│ JS (unsanitized): | |
//│ let Baz1; | |
//│ Baz1 = function Baz(z1) { return new Baz.class(z1); }; | |
//│ Baz1.class = class Baz extends Bar3.class { | |
//│ constructor(z) { | |
//│ let tmp2; | |
//│ tmp2 = this.z * 1; | |
//│ super(tmp2); | |
//│ this.z = z; | |
//│ } | |
//│ get baz() { | |
//│ return this.bar * 2; | |
//│ } | |
//│ toString() { return "Baz(" + globalThis.Predef.render(this.z) + ")"; } | |
//│ }; |
Here, the current scheme always treats the class parameter z
symbol as a field so it always code-gens z
as this.z
; but this is not valid in the pre-constructor (i.e., before super
is called). So it seems to me we should just treat all parameters the same, including class parameters, but classes would additionally get some derived symbol form that represents a field induced by a class parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the obvious thing to do is simply to desugar each class parameter z
into a normal parameter z
(VarSymbol
) along with a val
, in the class body, that binds a field named z
to that parameter, using a TermDefinition
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then it would have a proper BlockMemberSymbol
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ie desugar elaborate
class Foo(val z) with
blah
into
class Foo(z‹123›) with
val member:z‹124› = z‹123›
blah
bb1da72
to
ce9abc4
Compare
class Foo(val z) with
blah should now be elaborated into class Foo(z‹123›) with
val member:z‹124› = z‹123›
blah I didn't differentiate |
@@ -25,19 +25,27 @@ class Foo[A] with | |||
|
|||
|
|||
|
|||
// Note: the elaborator elaborates class parameters into additional field definitions; | |||
// this is why the following code yields two same errors. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed in the meeting, let's not duplicate the annotation here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't forget to remove this FIXME comment!
// FIXME: in super calls, class params should actually be viewed as a `VarSymbol`, not a `TermSymbol` wit owner
@@ -117,6 +117,7 @@ class InstSymbol(val origin: Symbol)(using State) extends LocalSymbol: | |||
|
|||
class VarSymbol(val id: Ident)(using State) extends BlockLocalSymbol(id.name) with NamedSymbol with LocalSymbol: | |||
val name: Str = id.name | |||
override def toLoc: Option[Loc] = id.toLoc |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
override def toLoc: Option[Loc] = id.toLoc | |
override def toLoc: Opt[Loc] = id.toLoc |
This PR improves the module method checks introduced in #233, and makes preparation in order to move all the checks to the resolution stage. It also fixes:
the problem that "module" parameters were not treated as modules
the problem that self referencing modules were not treated as modules
the problem that term definitions returning a module were not treated as modules