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

[TODO] Nim now allows modules with same name in a package #8614

Closed
wants to merge 6 commits into from

Conversation

timotheecour
Copy link
Member

@timotheecour timotheecour commented Aug 11, 2018

No language I know except Nim has this restriction; lifting it just makes sense

Nim now allows modules with same name in a package, eg:
foo/bar.nim and bar.nim

this avoids having to use previous hacks like foo/foo_bar.nim that were there to avoid module name clashes; these were not DRY.

this enables to have tests/stdlib/ospaths.nim instead of tests/stdlib/tospaths.nim for a test of ospaths (EDIT as done for 1 test in this PR)
likewise, it allows things like:

json/serialization
bson/serialization

redis/types
mongodb/types

etc which are more natural than: redis/redis_types

if a user wants to import 2 modules with same basename in 1 module, he can just write:

import json/serialization as jserialization
import bson/serialization

links

NOTE

  • suppose we have:
    /foo/bar/jesterRepo/util/baz.nim
    with /foo/bar/jesterRepo/jester.nimble
    it generates:
    jester.util as package name EDIT
    (ie using getPackageName which finds the first dir which contains a nimble file)

EDIT The following may be a bit surprising but are result of current placement of files in Nim:

stdlib.std.sha1
stdlib.pure.collections.intsets
compiler.compiler.prefixmatches # because compiler.nimble is under Nim/compiler.nimble instead of Nim/compiler/compiler.nimble => to be fixed in PR https://github.com/nim-lang/Nim/pull/8636
  • EDIT it generates package parents hierachically, exactly as follows:
    module ospaths -> package stdlib.pure (note: fully qualified) => package stdlib

  • EDIT files like these will be generated in nimcache:

stdlib.pure.bitops.c
stdlib.pure.math.c
stdlib.system.c
timn.bugs.exp_module_nonuniq.t01.c
  • EDIT example of things it generates during compilation (with --hint[CC]=on):
CC: stdlib.pure.collections.rtarrays
CC: stdlib.std.sha1
CC: compiler.compiler.prefixmatches
CC: stdlib.pure.concurrency.cpuinfo
CC: stdlib.impure.nre.private.util
CC: stdlib.impure.nre
CC: stdlib.deprecated.pure.asyncio
CC: stdlib.system

TODO

  • EDIT add tests => tests/modules/tnotuniquename1.nim
  • EDIT not yet sure how to handle this 1 particular line: registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} = ; @Araq ?

TODO (future PR)

depends on:

previous versions of this PR

a previous version of this PR was using a simpler scheme:
/foo/bar/jester/util/baz.nim was mapped to @foo@bar@jester@util@ as package name ; this caused issues, eg with registerCallback and other tests, and made packages depend on location of nimble packages on filesystem, which is not desirable

then I made changes to use @jester@util@ instead of @foo@bar@jester@util@ (ie using getPackageName to find package root)

then I made changes to use jester.util instead of @jester@util@ which looks more natural

@alehander92
Copy link
Contributor

It would be cool if this limitation is lifted, I also find that it just leads to hacky workarounds

@Araq
Copy link
Member

Araq commented Aug 12, 2018

FYI this was actually on my TODO list too for the upcoming release.

@@ -18,7 +18,9 @@ iterator myParentDirs(p: string): string =
proc resetPackageCache*(conf: ConfigRef) =
conf.packageCache = newPackageCache()

proc getPackageName*(conf: ConfigRef; path: string): string =
when false:
proc getPackageName*(conf: ConfigRef; path: string): string =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indenting here looks wrong, it should be 2 spaces where this appears to just be 1...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, why not just remove this code instead of disabling it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Contributor

@euantorano euantorano left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, I've been hit by this limitation a couple of times now and would definitely welcome this change!

@Clyybber
Copy link
Contributor

@Araq Is that TODO list public?

@dom96
Copy link
Contributor

dom96 commented Aug 13, 2018

Minor point, by why @?

@Araq
Copy link
Member

Araq commented Aug 13, 2018

@Clyybber With this feature implemented and my araq-misc branch merged, it'll be empty. (The other items are all on github.)

@Araq
Copy link
Member

Araq commented Aug 13, 2018

Minor point, by why @?

That won't stay, it's not allowed on Windows anyway.

@timotheecour
Copy link
Member Author

timotheecour commented Aug 14, 2018

@Araq @dom96

Minor point, by why @?
That won't stay, it's not allowed on Windows anyway.

Actually @ is allowed for filenames on windows, see https://stackoverflow.com/a/31976060/1426932 as well as green tests in #8629 which was a previous version of this PR using @ instead (I also tried to create foo@baron windows command prompt and it works)

However, I agree @ was not the best choice and now used . in this PR which fits better with rest of Nim.

PTAL (top-level PR msg reflects latest PR status)

@dom96
Copy link
Contributor

dom96 commented Aug 14, 2018

Why don't you just use _?

@timotheecour
Copy link
Member Author

timotheecour commented Aug 14, 2018

_ is bad because it creates ambiguities when folder or file contains _, which happens a lot, both in Nim repo and in other nimble repos, eg:
./lib/impure/db_mysql.nim
generates, with this PR, the following fully qualified name:
stdlib.impure.db_mysql

which is unambiguous (unless a Nim source dir/file contains an inner "." which we can disallow for dirs (it's already disallowed for nim files, and may even already be disallowed for Nim source dirs)

with your suggestion it would generate:
stdlib_impure_db_mysql
and would clash with following file, if it existed:
./lib/impure/db/mysql.nim
which maps to same string

(other eg: nim-ranges/ranges/ptr_arith.nim and ./doc/nimcache/manual/manual_snippet_119.nim)

. is just cleaner and fits better with rest of language which uses . for scope (eg ospaths.mysymbol)

@timotheecour
Copy link
Member Author

@Araq @dom96 PTAL: tests are green

import std/sha1 as sha1_2
# TODO: Error: cannot open file: stdlib/std/sha1; inconsistent with the fact we
# generate `stdlib.std.sha1`
# import stdlib/std/sha1 as sha1_3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why would import stdlib/std/sha1 be valid? It shouldn't be valid.

Copy link
Member

@Araq Araq left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is hard to follow and I don't understand why it's necessary. For the frontend you can just disable this check. For the backend you can replicate the Path structure or detect the part of the path required for disambiguation. Or you hash the full path and append it to the filename. These ideas should all lead to simpler code that doesn't touch so many parts of the compiler.

@@ -12,7 +12,7 @@ import ospaths
warning("uninit", off)
hint("processing", off)
#--verbosity:2
patchFile("stdlib", "math", "mymath")
patchFile("stdlib.pure", "math", "mymath")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get of this .pure requirement.

@@ -229,12 +229,20 @@ proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest, target: TTarg
r.addResult(test, target, expected.msg, given.msg, reSuccess)
inc(r.passed)

import compiler/options
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh come on, the tester does not import the compiler.

@@ -262,6 +270,7 @@ proc codegenCheck(test: TTest, target: TTarget, spec: TSpec, expectedMsg: var st
echo getCurrentExceptionMsg()
except IOError:
given.err = reCodeNotFound
echo getCurrentExceptionMsg()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is nothing to report here, reCodeNotFound is sufficient.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is introduced in this dependent PR #8631 and discussed there

@@ -92,7 +92,7 @@ proc patchFile*(package, filename, replacement: string) =
##
## .. code-block:: nim
##
## patchFile("stdlib", "asyncdispatch", "patches/replacement")
## patchFile("stdlib.pure", "asyncdispatch", "patches/replacement")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The .pure part is an implementation detail and should not be exposed.

@@ -16,19 +16,19 @@ from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir

template mathop(op) {.dirty.} =
registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`)
registerCallback(c, "stdlib.pure.math." & astToStr(op), `op Wrapper`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These should all not be changed, other tools also rely on registerCallback.

@@ -12,38 +12,53 @@ iterator myParentDirs(p: string): string =
var current = p
while true:
current = current.parentDir
if current.len == 0: break
# IMPROVE:parentDir is buggy, "foo.nim".parentDir should be ".", not ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What? It should be .? No.

var parents = 0
var dirs:seq[string] = @[]
var pkg = ""
var path_root = ""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The compiler and all of Nim's stdlib use camelCase.

@GULPF
Copy link
Member

GULPF commented Aug 19, 2018

I think the docgen must be changed as well, it currently puts every HTML file in the same directory which will cause conflicts if there are duplicate module names.

@dom96
Copy link
Contributor

dom96 commented Aug 19, 2018

I think the docgen must be changed as well, it currently puts every HTML file in the same directory which will cause conflicts if there are duplicate module names.

I disagree. Worst case is the user will have to write -o:my_module2.html.

@GULPF
Copy link
Member

GULPF commented Aug 19, 2018

I disagree. Worst case is the user will have to write -o:my_module2.html.

Using -o with a different file name means that module links that are generated by the docgen wont work. These are the links I'm referring to. Besides, writing the nim doc commands for individual modules isn't really feasibly in large projects (like Nims stdlib).

@Clyybber
Copy link
Contributor

@timotheecour @Araq Will we get this merged before 0.19? If the comments are addressed at least?

@Araq
Copy link
Member

Araq commented Aug 28, 2018

Unlikely, sorry. v0.19 is overdue and bugs like #7854 take up all resources. :-)

@Araq
Copy link
Member

Araq commented Dec 21, 2018

As I said.

This is hard to follow and I don't understand why it's necessary. For the frontend you can just disable this check. For the backend you can replicate the Path structure or detect the part of the path required for disambiguation. Or you hash the full path and append it to the filename. These ideas should all lead to simpler code that doesn't touch so many parts of the compiler.

@Araq Araq closed this Dec 21, 2018
@timotheecour timotheecour changed the title Nim now allows modules with same name in a package [TODO] Nim now allows modules with same name in a package Dec 21, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants