Comment by alcover
3 days ago
> (1) If I read "io.print", is this "the print function in the module io" or "the print method for the variable io"
I don't see the issue. Just look up the id ? Moreover, if modules are seen as objects, the meaning is quite the same.
> checking is much easier if the namespace is clear from the grammar.
Again (this time by the checker) just look up the symbol table ?
Let's say you have find foo::bar(), then we know that the path is <some path>::foo, the function is `bar` consequently we search for all modules matching the substring ::foo, and depending on whether (1) we get multiple matches (2) we only get a match that is not properly visible (3) we get a match that isn't imported, (4) we get no match or (5) we get a visible match, we print different things. In the case 1-4, we give good errors to allow the user to take the proper action.
If instead we had foo.bar(), we cannot know if this is the method "bar" on local or global foo, or a function "bar()" in a path matching the substring "foo". Consequently we cannot properly issue 4, since we don't know what the intent was.
So far, not so bad. Let's say it's instead foo::baz::bar(). In the :: case, we don't have any change in complexity, we simply match ::foo::baz instead.
However, for foo.baz.bar(), we get more cases, and let us also bring in the possibility of a function pointer being invoked: 1. It is invoking the method bar() on the global baz is a module that ends with "foo" 2. It is calling a function pointer stored in member bar on the global variable baz is a module that ends with "foo" 3. It is calling the function bar() in a module that ends with "foo.baz" 4. It is calling the function pointer stored in the global bar in a module that ends with "foo.baz" 5. It is invoking the method bar on the member baz of the local foo 6. It is calling a function pointer stored in the member bar in the member baz of the local foo
This might seem doable, but note that for every module we have that has a struct, we need to speculatively dive into it to see if it might give a match. And then give a good error message to the user if everything fails.
Note here that if we had yet another level, `foo.bar.baz.abc()` then the number of combinations to search increases yet again.
I think you are overcomplicating this.
This is exactly the syntax Python uses, and there is no "search" per se.
Either an identifier is in the current namespace or not.
And if it is in the current namespace, there can only be one.
The only time multiple namespaces are searched is when you are scoped within a function or class which might have a local variable or member of the same name.
> find foo::bar(), then we know that the path is <some path>::foo, the function is `bar` consequently we search for all modules matching the substring ::foo,
The only reason you need to have a search and think about all the possibilities is that you are deliberately allowing implicit lookups. Again, in Python:
1) Everything is explicit; but 2) you can easily create shorthand aliases when you want.
> note that for every module we have that has a struct, we need to speculatively dive into it to see if it might give a match. And then give a good error message to the user if everything fails.
Only if you rely on search, as opposed to, you know, if you 'import foo' then 'foo' refers to what you imported.