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

Ability to get reflifc::Module from any reflifc object. #27

Closed
FireFlyForLife opened this issue Aug 28, 2023 · 7 comments
Closed

Ability to get reflifc::Module from any reflifc object. #27

FireFlyForLife opened this issue Aug 28, 2023 · 7 comments

Comments

@FireFlyForLife
Copy link
Contributor

All reflifc types combine the ifc::File and some pointer/index, however the file is never exposed.

This might be partly a design decision, but for my current use case I need to check if a certain type/declaration from a certain module (so ifc::File, or reflifc::Module). To determine if a type is visibility or reachable.

Do you have any concerns with adding this to the API?

@AndreyG
Copy link
Owner

AndreyG commented Aug 29, 2023

If I understand your suggestion correctly, you are talking about method like Module owning_module() const. But I'm not sure how such method could be used?

@FireFlyForLife
Copy link
Contributor Author

For me, it's to check if the given Declaration is fully visible from ModuleA where I'm generating code for.

Lets say there is a function like this:

bool is_module_imported_in_module(reflifc::Module to_check, reflifc::Module module_, ifc::Environment& environment, bool use_imported = true)
{
	if (to_check == module_) {
		return true;
	}

	if (use_imported) {
		for (auto imported_module : module_.imported_modules(environment)) {
			if (to_check == imported_module) {
				return true;
			}
		}
	}

	for (auto exported_module : module_.exported_modules(environment)) {
		if (is_module_imported_in_module(to_check, exported_module, environment, false)) {
			return true;
		}
	}

	return false;
}

With the added API owning_module(). I can use it to check if the decl is from a module that is fully exported:

bool is_decl_visible(reflifc::Declaration my_decl, reflifc::Module root_module) {
    const bool owning_module_visible = is_module_imported_in_module(my_decl.owning_module(), root_module, g_environment);
    const bool decl_self_visible = my_decl.specifiers() & yadayada;
    return owning_module_visible && self_visible;
}

This is my use case at the moment.

@AndreyG
Copy link
Owner

AndreyG commented Aug 29, 2023

Firstly, owning_module() makes sense only for declarations, but not for types. Secondly, what should owning_module() return for a declaration attached to global module? I suppose null?

@FireFlyForLife
Copy link
Contributor Author

Maybe the wording is a bit confusing. But my understanding is that a ifc::File stores the types/decls & everything for 1 .ixx file. The global module fragments are still declared/included in that .ixx file and ends up in the ifc::File.

This is what I wanted to expose, which ifc::File the Decl/Type index belongs to. In this sense I was under the impression it made sense to also add owning_module() to Type and others.

Why do you say Types don't make sense to have a owning module?

@AndreyG
Copy link
Owner

AndreyG commented Aug 29, 2023

The global module fragments are still declared/included in that .ixx file and ends up in the ifc::File.

Right, but let's consider the following example

// ------ X.h ------
#pragma once

class X {};

// ----- M.ixx -----
module;
#include "X.h"
export module M;
export X g_x;
// `class X` is part exported from `M`, but it's attached not to module `M`, but to global module

// --- consumer.cpp ---
import M;
// `g_x` is visible here, but `X` is not

Why do you say Types don't make sense to have a owning module?

The only sort of types for which owning_module() makes sense is designated (which is plainly single declaration, see https://github.com/AndreyG/ifc-reader/blob/master/lib/core/include/ifc/Type.h#L98). But it doesn't make sense for all other sorts, i.e. Pointer/Reference/Array/QualifiedType/FunctionType/... and so on.

@FireFlyForLife
Copy link
Contributor Author

I think you are right on the types point. It only makes sense for Declarations. From all of the related code I've written thus far that's the final thing I need to check for.

The Global Module fragment I'm not really worried about. It's still part of the same .ifc file as all the other declarations, they just have the BasicSpecifiers::IsMemberOfGlobalModule flag set.

To illustrate, say you have a reflifc::Module and you call .scope_declarations(), those declarations that are in the Global Module Fragment already show up anyway. So it makes sense to allow .owning_module() to make it symmetrical.

So my question now would be, would you be okay .owning_module() (or another name with the same functionality). for reflifc::Declaration and all the variations of it (eg, AliasDeclaration, ScopeDeclaration)?

@AndreyG
Copy link
Owner

AndreyG commented Aug 29, 2023

Ok, let's add containing_file(). I'm definitely against name owning_module() firstly because of global module, and secondly because of partitions:

export module M;
export import :part1;
export import :part2;

export module M:part1;
export class X {};

export module M:part2;
export class Y {};

X and Y are attached to the same module M (i.e. M owns both of them), but containg_file() for them returns "part1.ixx" and "part2.ixx" respectively.

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

No branches or pull requests

2 participants