Open matthias-dunkel opened 1 year ago
I am currently looking into this issue. I print every import in the Namers resolve function. I changed line 59-61 to:
val imports = decl.imports collect {
case im @ source.Import(path) =>
Context.at(im) {
println(Context.module.source.name)
processDependency(path) }
}
For a file that imports nothing, I expected the output to be nothing. But actually the output is:
..\effekt\libraries\js\immutable\option.effekt
..\effekt\libraries\js\immutable\list.effekt
..\libraries\js\immutable\list.effekt
Somehow, this is imported, even when not used by the file.
Also, the standard library files are resolved with an absolute path, while every other import is resolved with a relative path (relative to the working directory!). That seems odd.
Tree.scala:
/**
* The type of whole compilation units
*
* Only a subset of definitions (FunDef and EffDef) is allowed on the toplevel
*
* A module declaration, the path should be an Effekt include path, not a system dependent file path
*
*/
case class ModuleDecl(path: String, imports: List[Import], defs: List[Def]) extends Tree
case class Import(path: String) extends Tree
How is an "Effekt include path" defined, and why should it not be a system file path?
Thanks for looking into it. 👍
First of all, what is a system file path? They are slightly different between operating systems (especially Windows...). Also, the language should work on the website with a virtualized unix file system.
I have been thinking about the design of name spacing, modules, dependencies, etc. Here are two observations:
I don't want to belittle your approach; I think you are right and we definitely need to do something. I would be very happy if you would be interested in driving this change, but we need a somewhat holistic solution.
I think we should separate (at least) two different use cases:
I believe (but might be wrong) that in scripting use we might require/import/include resources relatively or absolutely given source paths.
In project use, having a global project config and automatically important ALL files as specified in the project config might be a better option.
This should also interact well with generalizing paths to URIs, like gist files etc. It should also integrate well with git-based dependency management.
In script mode, I can imagine to write something like:
include git://otherproject.git#a136f451
def foo() = ...
which should result in cloning the repo somewhere, checking out the specified commit, building the project, and bringing the symbols into scope (this should also work in the REPL, btw.).
In a project mode, it might make more sense to specify this as a dependency in a config file.
@jiribenes pointed out that Go had bad experiences with using git
to distribute packages.
I agree that we should separate by use cases. I have a hard time understanding the current parsing step. When are the import files parsed? Are they parsed somewhere here for jvm: https://github.com/effekt-lang/effekt/blob/ff76871e5971fb8a9e730ddc0bf90efcaa76ff56/effekt/jvm/src/main/scala/effekt/context/IOModuleDB.scala#L27 :
I would like to go further with the project approach like this:
I know that is oversimplified. But I hope you get the idea.
Just to avoid confusion, before proceeding with an ad-hoc design, it would be wise to consider all of the wildly differing aspects of what a module is / can be:
In turn, this raises multiple questions such as:
Note that the decisions made around modules will have far-reaching consequences rippling into the rest of the language, so caution and proper planning must be employed.
For reference, here's a related issue in this repo with a preliminary module design: https://github.com/effekt-lang/effekt/issues/30
Also see #389 for future work on imports.
Currently, the import system seems to work like this: The import "path" needs to be relative to the directory you call the effekt compiler from. For example:
foo.effekt:
bar.effekt
Running this from root will with:
PATH\root> effekt bar.effekt
will lead to:bar.effekt:2:1: Cannot find source for root/foo
But will work when run from
PATH
This is not intuitive and leads to long
import
andmodule
statements.Solution
I think the
module
statements should be relative to the folder the effekt file lives in. So there is a mapping between folders and modules. The module's child and parent relationship corresponds to the folder hierarchy. Import statement should import from the declared modules. The file should not need to know where the module is to import from it, otherwise it is counterintuitive to modules. Just as it works with the standard library.