-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
help Julia get further in bootstrapping this branch
- Loading branch information
Showing
2 changed files
with
4 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
e5afe78
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.
this is mostly sufficient to get julia through bootstrapping, with some comments:
.1. because of some implementation details, defining the call method twice like this populates the method tables better (see below). this is necessary since
start(Array{Any,1})
isn't defined until much later, but we can't define it earlier because it needs support for numbers, which is defined inint.jl
, after this would fails):.2. the system image can't be re-saved from an old image because generic functions aren't really allowed in
Core
(since it populates the method table with references to the old base module, and serialize indump.c
will not like that). maybe it is possible to drop any method in the method tablecall.env
that reference the old module?.3. dispatching
call{T}(Type{T},x)
toconvert(T,x)
fails to take into account that a type may be constructed by calling its constructor with multiple arguments (e.g., bootrapping fails with a no method error oncall(Complex{Bool}, false, true)
). not dispatchingcall
toconvert
(as I have here) fails to take into account that some types can't be constructed by calling their constructors (e.g.Int(1)
/call(Int,1)
doesn't work here). having both defined is just ugly and inconsistent. perhaps you could just defineconst convert = call
as follows:However, this doesn't work since we want
convert(String, "HI")
to be a no-op, butString("HI")
maybe not. This implies that we would do need to have a uniqueconvert
method that is used internally. I'm not sure how to handle deprecation, but it seems that the bitstypes constructors will need to be migrated over to extendingcall
, notconvert
. thenconvert
can be modified to try the defaultcall
constructor as a fallback, rather than the reverse.cross ref: #8008
@stevengj
e5afe78
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.
A good approach to the bootstrapping problem is to have Core.call and Base.call be separate functions. Code in
Core
usesCore.call
, and everything else usesBase.call
.Base.call
can fall back toCore.call
. This is the "layered" kind of separate compilation julia can handle.I don't imagine
convert(String,"HI")
andString("HI")
ever being different.It's not correct for
convert
to fall back tocall
.Constructors will be changed to add methods to
call
, so thecall(T::Type, x) = convert(T,X)
fallback should be neatly shadowed in those cases.e5afe78
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.
Agreed, this is just also slightly complex because codegen then has multiple copies of
call
that it can call, and it needs to be able to pick the right onefor String this is probably true, but for container types, it might not. The only example I can think of right now is in
Gtk
, where:Frame(Frame())
should get you aFrame
containing aFrame
, whereasconvert(Frame, Frame())
should not.I think I am in agreement now, just had to think through it more.
taking this into account, I was trying to decide if a rename of
convert
would be helpful (and definingconst convert = call
) would help with the transition, and for writing code to work with both versions. I don't know.e5afe78
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.
The
Frame
example is perfect --- I don't know why it never occurred to me. For nested or stateful objects, constructing is clearly different from converting.e5afe78
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.
Yes, that's a great example. Conflating constructing and converting has always struck me as fishy, but this really nails why.
e5afe78
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.
This also reminds me we need to be careful: while
Int(1.0)
is a perfectly good way to convert 1.0 to 1, it's not at all clear whetherArray([1])
converts the argument to an array (no-op) or makes a new array of arrays.e5afe78
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.
No, this isn't a problem, because the constructor will eventually add methods to
call
as Jeff mentioned. The point is that defining aconvert
method should always define a single-argument constructor, but the converse is not true. And if you explicitly define both a single-argument constructor and aconvert
method, the former will shadow the latter when called as a constructor.e5afe78
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.
@vtjnash, when I try to
make clean && make
from this branch I still get an error:Where is it going wrong?
e5afe78
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 could define that
Frame(Frame())
is a no-op – and that nesting objects always requires a separate function call – such that constructing and converting are always equivalent, but that is just inconvenient in this case. I considered givingArray([1])
as an example, but since that is currently undefined, I decided not to use it.This also makes a decent counter-example to above. While
convert(Array,1)
seems to obviously returnInt[1]
,Array(1)
might return eitherFloat64[]
orInt[1]
, depending on which behavior you want to consider to be the base case.@stevengj see my 2nd bullet point in my initial comment, and Jeff's response in the next comment