Skip to content
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

Parser error when trying to add module scope to an export #14472

Open
timholy opened this issue Dec 23, 2015 · 13 comments
Open

Parser error when trying to add module scope to an export #14472

timholy opened this issue Dec 23, 2015 · 13 comments
Labels
modules parser Language parsing and surface syntax

Comments

@timholy
Copy link
Member

timholy commented Dec 23, 2015

(Note: clearer statement and example in #14472 (comment))

I'd like it if using A could export a symbol from module B, using the module name as a qualifier:

export B.save

This has come up as an issue in the interaction between JLD and FileIO. FileIO exports load and save; after long discussion (CC @SimonDanisch), we decided that modules using FileIO should not extend these methods, but that FileIO should dispatch to unexported functions of the same name: in other words, FileIO should call JLD.save, a function which is not exported by JLD, even though JLD has using FileIO in its definition.

The problems come when a module like JLD wants to (perhaps for backwards-compatibility reasons) export FileIO's save rather than its own save.

Simple example:

module MyFormat

using FileIO

# Here's the line I'd like to uncomment:
# export FileIO.save

# In-line FileIO registration (for testing purposes)
add_format(format"MYFMT", "MYFMT", ".myfmt", [:MyFormat])

function save(f::File{format"MYFMT"}, x)
    open(filename(f), "w") do io
        write(io, magic(format"MYFMT"))
        print(io, '\n')
        print(io, "x = ", x)
    end
end

end

But if I uncomment that export line, I get

julia> using MyFormat
ERROR: LoadError: syntax: extra token "." after end of expression
 in include at ./boot.jl:261
 in include_from_node1 at ./loading.jl:392
 in eval at ./boot.jl:264
 [inlined code] from ./sysimg.jl:14
 in require at ./loading.jl:332
 in eval at ./boot.jl:264
while loading /tmp/MyFormat.jl, in expression starting on line 6

Obviously we could solve this by calling the internal method _save, but at this point it would be nicer not to have to change our expectations of packages that use FileIO.

Since this looks like a parser error, I'm wondering whether this could be fixed by changing the parser? Or would this introduce some other kind of problem?

Mildly related: #1986.

@timholy timholy added the parser Language parsing and surface syntax label Dec 23, 2015
@JeffBezanson
Copy link
Member

In this example, does MyFormat.save extend FileIO.save? If not, I don't think this will be possible. When you get name x from M via using, you have to get M.x.

Otherwise, I suppose this is equivalent to import FileIO.save; export save?

@ssfrr
Copy link
Contributor

ssfrr commented Dec 29, 2015

@timholy did the discussion on whether to extend FileIO.save happen in an issue I can look at? It's tripped me up in the past and I'm curious, but don't want to derail this thread too badly. :)

@timholy
Copy link
Member Author

timholy commented Dec 31, 2015

In this example, does MyFormat.save extend FileIO.save?

No, it doesn't. Instead, FileIO.save calls MyFormat.save with explicit scoping.

@timholy did the discussion on whether to extend FileIO.save happen in an issue I can look at?

You can start reading here:
JuliaIO/FileIO.jl#43 (comment)

@timholy
Copy link
Member Author

timholy commented Dec 31, 2015

When you get name x from M via using, you have to get M.x.

I can change that using to import, if it changes anything.

@bicycle1885
Copy link
Member

Is there any progress here? I also want the export syntax like export FileIO.save. In my case, I want to write like:

module Seq

module RE
type Regex
    # ...
end

function matched(re::RegexMatch)
    # ...
end

macro prosite_str(pat)
    $(Regex(pat))
end
end # module RE

# this syntax is not supported!
export .RE.Regex, .RE.matched, .RE.@prosite_str

end # module Seq

Or more compactly:

# this syntax is not supported!
export .RE: Regex, matched, @prosite_str

Note that this is really symmetrical to import. So, I think it would be very nice if we had that.

@timholy
Copy link
Member Author

timholy commented Mar 29, 2016

@bicycle1885, if should work if RE exports Regex, matched, and @prosite_str, say using RE inside Seq, and then have Seq re-export all those same things. The Reexport package makes this a little nicer.

This issue is specific to a case where module A has its own save method but wishes to export a save method from B instead.

@bicycle1885
Copy link
Member

@timholy Thank you. I know it is possible, but I'd like to export as I wrote above. Names exported by the RE module is not in its parent module (Seq). It is also hard to keep multiple export statements synchronized. Reexport.jl works file, but I think this should be supported in the Julia compiler.

It seems to me that your issue and my issue are very similar and can be solved in one fix. Should I open a new issue about my stuff?

@timholy
Copy link
Member Author

timholy commented Oct 4, 2016

Simpler example:

julia> module A

       export fancy
       fancy(x) = 2x

       end
A

julia> module B

       import A
       fancy(x) = 3x
       export A.fancy

       end

ERROR: syntax: extra token "." after end of expression

Here I'd like to have using B make available A's version of fancy.

Ref JuliaLang/METADATA.jl#6619 (comment)

@vtjnash
Copy link
Member

vtjnash commented Jul 13, 2017

dup #1986

@vtjnash vtjnash closed this as completed Jul 13, 2017
@timholy timholy changed the title Exporting one module's symbols from another Exporting one module's save rather than its own save Sep 21, 2017
@timholy
Copy link
Member Author

timholy commented Sep 21, 2017

While I see how my description seems similar to #1986, it's not really the same thing; I've clarified an important distinction in the title. I have no problems with listing the specific methods I want to export, I just want to control the module scope of the exports explicitly. But it's a parser error:

julia> module A
       export foo
       foo() = 1
       end
A

julia> module B
       using A
       foo() = 2
       export A.foo
ERROR: syntax: extra token "." after end of expression

Didn't even let me finish the module definition. We're allowed to say import A.foo, why not export A.foo?

@timholy timholy reopened this Sep 21, 2017
@timholy timholy changed the title Exporting one module's save rather than its own save Parser error when trying to add module scope to an export Sep 21, 2017
@timholy
Copy link
Member Author

timholy commented Sep 21, 2017

I'm not a schemer (and would have to re-teach myself the language to tackle this myself), but I suspect the fix is here.

@JeffBezanson
Copy link
Member

To clarify, I assume you want B.foo() to return 2, but the foo you get from using B to return 1? If so, we can't support that without some redesign. A module can have only one binding for a name, and the same one is used for using and dot access.

@timholy
Copy link
Member Author

timholy commented Oct 31, 2017

Sorry I missed your reply. Yes, you understood the request precisely. I hear you on the challenges. Presumably not 1.0 material? Or even 1.x? I recognize the potential for confusion here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
modules parser Language parsing and surface syntax
Projects
None yet
Development

No branches or pull requests

6 participants