nyan icon indicating copy to clipboard operation
nyan copied to clipboard

__init__.nyan support

Open TheJJ opened this issue 5 years ago • 3 comments

Add support for __init__.nyan files that behave like Python's __init__.py. When a folder is imported, this file is loaded and its definitions are loaded.

The definitons are handled just like a regular nyan file. Definitions in /rofl.nyan are loaded exactly the same way as the same definitions in /rofl/__init__.py. Nyan will abort loading if both a /name.nyan and /name/... folder are a candidate for loading.

The __init__.nyan is designed for imports (and alias definitions), that redirect to declarations of other nyan files in the same (or a sub-)folder.

TheJJ avatar Nov 05 '18 21:11 TheJJ

I'd be interested in working on this. When trying to import name two possibilities would be tested for: /name.nyan and /name/__init__.nyan. If zero or two files exist with that name, an error gets thrown.

It should be pretty simple to generate those strings and check if the corresponding files exist using something like the <filesystem> library. I assume that this should be added to the Namespace::from_filename() method. Is that right?

apainintheneck avatar Apr 07 '22 00:04 apainintheneck

Python prefers the package over the single file, but throwing an error would be better i think when both are present. Yes, Namespace::from_filename has to be adjusted, but we have to adjust the whole import mechanism, and the entry point for that is Database::load.

In there the namespace_to_import and namespace_to_import.to_filename() have to be aware of the possible filenames.

TheJJ avatar Apr 07 '22 20:04 TheJJ

Yeah, this is a little more complex than I first thought. Let me see if I've got this right.

Like you said Database::load() is the entry point. A filename is passed to load. This filename is used to initialize the first namespace using Namespace::from_filename(). Both Database::load() and Namespace::from_filename() require a file path that ends in .nyan and will complain if they don't get that. So it's currently not possible to pass an init file like namespace/__init__.nyan to either of them by just specifying the namespace namespace. You need to specify the file explicitly.

Inside the Database::load() method is a loop where all of the imports contained in .nyan files are imported one at a time. This works by taking a namespace from the to_import vector and converting it to a filename using Namespace::to_filename() to read the file.

This brings up the first big difficulty. Both /name.nyan and /name/__init__.nyan will be in the same namespace but should produce different filenames for obvious reasons. It almost seems like those two things, the namespace and the filename, should be stored separately in the Namespace class but I don't know if it makes sense to store the filename there. It's not really directly related to the namespaces; it just helps with importing.

Then all imports are read from that file and added to the to_import vector by using the NamespaceFinder class to parse said file. These Namespace objects are initialized with a different constructor that takes an IDToken. This token already contains the components necessary to build a namespace and a path from that namespace.

That being said it assumes once again that each file associated with a namespace is that namespace(with / instead of .) + .nyan which wouldn't be the case if an init file was possible.

So I'm starting to think that every constructor would need to be updated to check for init files and that there should be a flag to indicate that this namespace is connected with an init file. If the flag is not set, [name, space] would become /name/space.nyan. If the flag is set, [name, space] would become /name/space/__init__.nyan. It also changes where relative imports need to be imported from too, right? /name vs /name/space. Plus, I'm not really sure how this would work with nested imports.

The simplest thing to do would be to only allow top-level init files because that would mean only changing the Namespace::from_filename() and Namespace::to_filename() methods but that's probably not what we want, right? That means all of the other constructors would need to be updated as a result. Or at least that's how I see it. There is probably still a bunch of stuff I'm missing though.

apainintheneck avatar Apr 11 '22 07:04 apainintheneck