Cross-module extern statements #168

Closed
opened 2024-04-01 21:20:38 +01:00 by deavmi · 8 comments
Owner

Purpose ✍️

To be able to extern a statement in module a, have module b import a and have that extern statement also accessible to b via a.<externName>.

Why?

All extern-like statements must become automatically private. This will stop them from being accessible outside to other modules which would cause them to get double externed. I mean, is that a problem. We could maybe handle it. But maybe not for now?

## Purpose ✍️ To be able to extern a statement in module `a`, have module `b` import `a` and have that extern statement also accessible to `b` via `a.<externName>`. ## Why? All `extern`-like statements must become automatically `private`. This will stop them from being accessible outside to other modules which would cause them to get double externed. I mean, is that a problem. We could _maybe_ handle it. But maybe not for now?
deavmi added the
question
label 2024-04-01 21:20:38 +01:00
deavmi self-assigned this 2024-04-01 21:20:51 +01:00
deavmi added this to the Code emit project 2024-04-01 21:20:54 +01:00
deavmi added the
emit
parser
labels 2024-04-01 21:21:02 +01:00
deavmi added this to the Clean ups milestone 2024-04-01 21:21:04 +01:00
deavmi added the due date 2024-04-05 2024-04-01 21:26:30 +01:00
Author
Owner

Okay there are a few more things to work on maybe,.... but these are low priority, so I can stop working on this PR for now at least


Last few things

  • DGen to emit extern variables (not just functions)
  • All extern-like statements must become automatically private. This will stop them from being accessible outside to other modules which would cause them to get double externed. I mean, is that a problem. We could maybe handle it. But maybe not for now? #168
  • Fix merge conflicts from vardec_varass_dependency

With regards to the second item in this list I think it actually may not require much work to get right. Look when we generate the externs for module import system we do so by placing extern <type> <name>, where <name> is the Entity's name regardless of whether it isExternal() or not.

Hence it should just work. The only part we must worry about is that we must NOT symbol map the Entity's (Variables) which are extern.


So basically this:

string signature;

// Extract the Variable's type
Type varType = typeChecker.getType(var.context.container, var.getType());

// Decide on the symbol's name
string symbolName;

// If it is NOT extern then map it
if(!var.isExternal())
{
	// FIXME: Set proper scope type
    symbolName = mapper.map(var, ScopeType.GLOBAL);
}
// If it is extern, then leave it as such
else
{
	symbolName = var.getName()
}

// <type> <name>
signature = typeTransform(varType)~" "~symbolName;

return signature;
> Okay there are a few more things to work on maybe,.... but these are low priority, so I can stop working on this PR for now at least > > --- > > ### Last few things > > - [x] `DGen` to emit extern variables (not **just** functions) > - [ ] All `extern`-like statements must become automatically `private`. This will stop them from being accessible outside to other modules which would cause them to get double externed. I mean, is that a problem. We could _maybe_ handle it. But maybe not for now? #168 > - [x] Fix merge conflicts from `vardec_varass_dependency` With regards to the second item in this list I think it actually _may_ not require much work to get right. Look when we generate the externs for module import system we do so by placing `extern <type> <name>`, where `<name>` is the `Entity`'s name regardless of whether it `isExternal()` or not. Hence it _should_ just work. The only part we must worry about is that we must **NOT** symbol map the `Entity`'s (`Variable`s) which **are extern**. --- So basically this: ```d string signature; // Extract the Variable's type Type varType = typeChecker.getType(var.context.container, var.getType()); // Decide on the symbol's name string symbolName; // If it is NOT extern then map it if(!var.isExternal()) { // FIXME: Set proper scope type symbolName = mapper.map(var, ScopeType.GLOBAL); } // If it is extern, then leave it as such else { symbolName = var.getName() } // <type> <name> signature = typeTransform(varType)~" "~symbolName; return signature; ```
Author
Owner

Okay there are a few more things to work on maybe,.... but these are low priority, so I can stop working on this PR for now at least


Last few things

  • DGen to emit extern variables (not just functions)
  • All extern-like statements must become automatically private. This will stop them from being accessible outside to other modules which would cause them to get double externed. I mean, is that a problem. We could maybe handle it. But maybe not for now? #168
  • Fix merge conflicts from vardec_varass_dependency

With regards to the second item in this list I think it actually may not require much work to get right. Look when we generate the externs for module import system we do so by placing extern <type> <name>, where <name> is the Entity's name regardless of whether it isExternal() or not.

Hence it should just work. The only part we must worry about is that we must NOT symbol map the Entity's (Variables) which are extern.


So basically this:

string signature;

// Extract the Variable's type
Type varType = typeChecker.getType(var.context.container, var.getType());

// Decide on the symbol's name
string symbolName;

// If it is NOT extern then map it
if(!var.isExternal())
{
	// FIXME: Set proper scope type
    symbolName = mapper.map(var, ScopeType.GLOBAL);
}
// If it is extern, then leave it as such
else
{
	symbolName = var.getName()
}

// <type> <name>
signature = typeTransform(varType)~" "~symbolName;

return signature;

Okay but wait, this is fine and all but technically if we request a signature for a variable then it should also place the extern in front of it.

This is where the problemo lies. Who's resposibility. I say this because the function siganture generator does this and therefore, to stay consistent, so should the Variable-based one.

So:

// If if is external then it needs `extern ...`
if(var.isExternal())
{
    signature = "extern "~signature;
}
> > Okay there are a few more things to work on maybe,.... but these are low priority, so I can stop working on this PR for now at least > > > > --- > > > > ### Last few things > > > > - [x] `DGen` to emit extern variables (not **just** functions) > > - [ ] All `extern`-like statements must become automatically `private`. This will stop them from being accessible outside to other modules which would cause them to get double externed. I mean, is that a problem. We could _maybe_ handle it. But maybe not for now? #168 > > - [x] Fix merge conflicts from `vardec_varass_dependency` > > With regards to the second item in this list I think it actually _may_ not require much work to get right. Look when we generate the externs for module import system we do so by placing `extern <type> <name>`, where `<name>` is the `Entity`'s name regardless of whether it `isExternal()` or not. > > Hence it _should_ just work. The only part we must worry about is that we must **NOT** symbol map the `Entity`'s (`Variable`s) which **are extern**. > > --- > > So basically this: > > ```d > string signature; > > // Extract the Variable's type > Type varType = typeChecker.getType(var.context.container, var.getType()); > > // Decide on the symbol's name > string symbolName; > > // If it is NOT extern then map it > if(!var.isExternal()) > { > // FIXME: Set proper scope type > symbolName = mapper.map(var, ScopeType.GLOBAL); > } > // If it is extern, then leave it as such > else > { > symbolName = var.getName() > } > > // <type> <name> > signature = typeTransform(varType)~" "~symbolName; > > return signature; > ``` Okay but wait, this _is_ fine and all but technically if we request a signature for a `variable` then it _should_ also place the `extern` in front of it. This is where the problemo lies. Who's resposibility. I say this because the function siganture generator does this and therefore, to stay consistent, so should the `Variable`-based one. So: ```d // If if is external then it needs `extern ...` if(var.isExternal()) { signature = "extern "~signature; } ```
Author
Owner

And now we shall run into expected problems that should be fixed in the ModuleExternStmts thing.

And now we shall run into expected problems that _should_ be fixed in the `ModuleExternStmts` thing.
Author
Owner

And now we shall run into expected problems that should be fixed in the ModuleExternStmts thing.

Heheh:

extern extern uint8_t p;
> And now we shall run into expected problems that _should_ be fixed in the `ModuleExternStmts` thing. Heheh: ```c extern extern uint8_t p; ```
Author
Owner

And now we shall run into expected problems that should be fixed in the ModuleExternStmts thing.

Heheh:

extern extern uint8_t p;

Okay, but now that it is fixed we could also then do checks in the ModExternSttmsd that yanks out the extern part if is knows the entity the signature is requested for is extern.

This would then make the following evar/efuncs:

extern extern uint8_t p;
extern extern uint8_t s();

into:

extern uint8_t p;
extern uint8_t s();

The checks are therefore basically like this:

// Emit public functions
foreach(Function func; mos.funcs())
{
	// Generate signature
	string signature = generateSignature(func);

	// Decide whether or not `extern` is needed
	string externPart = func.isExternal() ? "" : "extern ";

	// Generate the emit
	string externEmit = format("%s%s;", externPart, signature);

	gprintln(format("FuncExternEmit: '%s'", externEmit));
	modOut.writeln(externEmit);
}

// Emit public variables
foreach(Variable var; mos.vars())
{
	// Generate signature
	string signature = generateSignature_Variable(var);

	// Decide whether or not `extern` is needed
	string externPart = var.isExternal() ? "" : "extern ";

	// Generate the emit
	string externEmit = format("%s%s;", externPart, signature);

	gprintln(format("VarExternEmit: '%s'", externEmit));
	modOut.writeln(externEmit);
}
> > And now we shall run into expected problems that _should_ be fixed in the `ModuleExternStmts` thing. > > Heheh: > > > ```c > extern extern uint8_t p; > ``` Okay, but now that it _is_ fixed we could also then do checks in the `ModExternSttmsd` that yanks out the `extern` part if is _knows_ the entity the signature is requested for is `extern`. This would then make the following `evar`/`efunc`s: ```c extern extern uint8_t p; extern extern uint8_t s(); ``` into: ```c extern uint8_t p; extern uint8_t s(); ``` --- The checks are therefore basically like this: ```d // Emit public functions foreach(Function func; mos.funcs()) { // Generate signature string signature = generateSignature(func); // Decide whether or not `extern` is needed string externPart = func.isExternal() ? "" : "extern "; // Generate the emit string externEmit = format("%s%s;", externPart, signature); gprintln(format("FuncExternEmit: '%s'", externEmit)); modOut.writeln(externEmit); } // Emit public variables foreach(Variable var; mos.vars()) { // Generate signature string signature = generateSignature_Variable(var); // Decide whether or not `extern` is needed string externPart = var.isExternal() ? "" : "extern "; // Generate the emit string externEmit = format("%s%s;", externPart, signature); gprintln(format("VarExternEmit: '%s'", externEmit)); modOut.writeln(externEmit); } ```
Author
Owner

And now we shall run into expected problems that should be fixed in the ModuleExternStmts thing.

Heheh:

extern extern uint8_t p;

Okay, but now that it is fixed we could also then do checks in the ModExternSttmsd that yanks out the extern part if is knows the entity the signature is requested for is extern.

This would then make the following evar/efuncs:

extern extern uint8_t p;
extern extern uint8_t s();

into:

extern uint8_t p;
extern uint8_t s();

The checks are therefore basically like this:

// Emit public functions
foreach(Function func; mos.funcs())
{
	// Generate signature
	string signature = generateSignature(func);

	// Decide whether or not `extern` is needed
	string externPart = func.isExternal() ? "" : "extern ";

	// Generate the emit
	string externEmit = format("%s%s;", externPart, signature);

	gprintln(format("FuncExternEmit: '%s'", externEmit));
	modOut.writeln(externEmit);
}

// Emit public variables
foreach(Variable var; mos.vars())
{
	// Generate signature
	string signature = generateSignature_Variable(var);

	// Decide whether or not `extern` is needed
	string externPart = var.isExternal() ? "" : "extern ";

	// Generate the emit
	string externEmit = format("%s%s;", externPart, signature);

	gprintln(format("VarExternEmit: '%s'", externEmit));
	modOut.writeln(externEmit);
}

Looks like this solution works.

> > > And now we shall run into expected problems that _should_ be fixed in the `ModuleExternStmts` thing. > > > > Heheh: > > > > > > ```c > > extern extern uint8_t p; > > ``` > > Okay, but now that it _is_ fixed we could also then do checks in the `ModExternSttmsd` that yanks out the `extern` part if is _knows_ the entity the signature is requested for is `extern`. > > This would then make the following `evar`/`efunc`s: > > ```c > extern extern uint8_t p; > extern extern uint8_t s(); > ``` > > into: > > ```c > extern uint8_t p; > extern uint8_t s(); > ``` > > --- > > The checks are therefore basically like this: > > > ```d > // Emit public functions > foreach(Function func; mos.funcs()) > { > // Generate signature > string signature = generateSignature(func); > > // Decide whether or not `extern` is needed > string externPart = func.isExternal() ? "" : "extern "; > > // Generate the emit > string externEmit = format("%s%s;", externPart, signature); > > gprintln(format("FuncExternEmit: '%s'", externEmit)); > modOut.writeln(externEmit); > } > > // Emit public variables > foreach(Variable var; mos.vars()) > { > // Generate signature > string signature = generateSignature_Variable(var); > > // Decide whether or not `extern` is needed > string externPart = var.isExternal() ? "" : "extern "; > > // Generate the emit > string externEmit = format("%s%s;", externPart, signature); > > gprintln(format("VarExternEmit: '%s'", externEmit)); > modOut.writeln(externEmit); > } > ``` Looks like this solution works. ✅
deavmi added spent time 2024-04-07 12:15:27 +01:00
1 minute
deavmi added spent time 2024-04-07 12:15:32 +01:00
1 hour
Author
Owner

We allow cross-module extern usage, it automagically works and the DGen emitter has now been updated to make it work.

We allow cross-module extern usage, it automagically works _and_ the `DGen` emitter has now been updated to make it work.
deavmi added reference feature/multi_module 2024-04-07 12:16:13 +01:00
Author
Owner

This is done

This is done ✅
Sign in to join this conversation.
No Milestone
No project
No Assignees
1 Participants
Notifications
Total Time Spent: 1 hour 1 minute
deavmi
1 hour 1 minute
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

2024-04-05

Dependencies

No dependencies set.

Reference: tlang/tlang#168
No description provided.