www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Why the compiler dosen't enforce correct module declarations?

reply Ary Manzana <ary esperanto.org.ar> writes:
I can have three files:

main.d:
---
module one;

import two;
import lala.la;

void main() {
    foo();
    bar();
}
---

other.d
---
module two;

import std.stdio;

void foo() {
    writefln("Hello!");
}
---

dir/some_other.d
---
module lala.la;

import std.stdio;

void bar() {
    writefln("Hello!!");
}
---

and compile them with no problem:
dmd main.d other.d dir/some_other.d

Shouldn't the compiler say "Wait, you are saying that module one is in 
file main.d, module two is in other.d and module lala.la is in 
dir/some_other.d, this isn't quite well"? In 
http://www.digitalmars.com/d/module.html it states:

"The packages correspond to directory names in the source file path."
"The module name is the file name with the path and extension stripped off."

Why this isn't honored by the compiler?

My worry is, if this is valid, then in an IDE you can't just assume 
directories are packages, and filenames (path and extension stripped 
off) are modules, since this is not mandatory. Then it's a lot harder to 
do. Further, it complicates things since probably nobody wants to name a 
module with a name and path that dosen't match the underlying 
filesystem's name and path. So enforcing this in a compiler eliminates 
"bugs".
May 12 2007
next sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Ary Manzana wrote

 In 
 http://www.digitalmars.com/d/module.html it states:

| The ModuleDeclaration sets the name of the module and what package | it belongs to. If absent, the module name is taken to be the same | name (stripped of path and extension) of the source file name. Please read carefully. -manfred
May 12 2007
parent reply Ary Manzana <ary esperanto.org.ar> writes:
Manfred Nowak escribió:
 Ary Manzana wrote
 
 In 
 http://www.digitalmars.com/d/module.html it states:

| The ModuleDeclaration sets the name of the module and what package | it belongs to. If absent, the module name is taken to be the same | name (stripped of path and extension) of the source file name. Please read carefully.

So what's the point of settings a package and module name different than what's in the filesystem?
May 12 2007
parent reply Chris Nicholson-Sauls <ibisbasenji gmail.com> writes:
Ary Manzana wrote:
 Manfred Nowak escribió:
 Ary Manzana wrote

 In http://www.digitalmars.com/d/module.html it states:

| The ModuleDeclaration sets the name of the module and what package | it belongs to. If absent, the module name is taken to be the same | name (stripped of path and extension) of the source file name. Please read carefully.

So what's the point of settings a package and module name different than what's in the filesystem?

Its useful as an alternative means of doing platform-versioning. (At least I remember this working... I might just be crazy.) For example: Given project: main.d - module main; util_win32.d - module util; util_linux.d - module util; You may now simply `import util;` in main, and on the command line pass the appropriate util module. I'm sure there might be another use as well, but I admit that even this one has limited value -- aside from avoiding having a redundant version(){}else{} block at the beginning of all modules importing util, but we have two different ways of avoiding that: a go-between module with a version'd public import of util, or a mixin. (Possibly even a mixin(import()).) -- Chris Nicholson-Sauls
May 12 2007
parent reply Ary Manzana <ary esperanto.org.ar> writes:
Chris Nicholson-Sauls escribió:
 Ary Manzana wrote:
 Manfred Nowak escribió:
 Ary Manzana wrote

 In http://www.digitalmars.com/d/module.html it states:

| The ModuleDeclaration sets the name of the module and what package | it belongs to. If absent, the module name is taken to be the same | name (stripped of path and extension) of the source file name. Please read carefully.

So what's the point of settings a package and module name different than what's in the filesystem?

Its useful as an alternative means of doing platform-versioning.

Why use an alternative of the built-in version system? Also, if you have many versioned modules (a1_win32.d, a1_linux.d, b1_win32.d, b1_linux.d, etc.) you need to change the command line for each of the modules, instead of just changing the version passed. You also have to tell the other developers: remember not to use the version flag, but to change the suffix of the filenames according to the version... Maybe doing the suffix thing is valid for C or C++, but I think D tries to solve that using versions, and not using them seems awkward to me.
May 12 2007
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Ary Manzana wrote

 Why use an alternative of the built-in version system?

The version system is not equivalent to the module naming system. -manfred
May 12 2007
next sibling parent reply Ary Manzana <ary esperanto.org.ar> writes:
Manfred Nowak escribió:
 Ary Manzana wrote
 
 Why use an alternative of the built-in version system?

The version system is not equivalent to the module naming system.

Ok. My point is that it is totaly unnecessary to have the module declaration say something different than it's location relative to the include source path. This is like things work in Java, for example: you get an error if the package declaration and the filesystem dosen't match. Why not apply the same in D?
May 12 2007
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Ary Manzana wrote:
 Manfred Nowak escribió:
 Ary Manzana wrote

 Why use an alternative of the built-in version system?

The version system is not equivalent to the module naming system.

Ok. My point is that it is totaly unnecessary to have the module declaration say something different than it's location relative to the include source path. This is like things work in Java, for example: you get an error if the package declaration and the filesystem dosen't match. Why not apply the same in D?

I plan to use this while DDL is out of commission. For instance: I have a class engine.gx.camera.Camera, which is just the interface declaration (no actual contents). I then have two different implementations: one for GL and one for D3D; they both need to have the same module name, but they exist in totally different places on the physical filesystem. And don't say "just use version()s" since I really don't want to have to go around putting in version flags in every place this switch happens. I just want to do it once at compile time and be done with it. Hell, once DDL is working again, they won't even be linked together at all. The whole point of this is to allow someone to swap out which implementation to use at run time; version()s won't let you do that :) Besides, I don't see that this is a huge problem. IDEs can just assume the "normal" behaviour holds, and if they find it doesn't they can either ignore it, or flag the modules in question for having odd names. -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 12 2007
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Daniel Keep wrote:
 
 Ary Manzana wrote:
 Manfred Nowak escribió:
 Ary Manzana wrote

 Why use an alternative of the built-in version system?


declaration say something different than it's location relative to the include source path. This is like things work in Java, for example: you get an error if the package declaration and the filesystem dosen't match. Why not apply the same in D?

I plan to use this while DDL is out of commission. For instance: I have a class engine.gx.camera.Camera, which is just the interface declaration (no actual contents). I then have two different implementations: one for GL and one for D3D; they both need to have the same module name, but they exist in totally different places on the physical filesystem. And don't say "just use version()s" since I really don't want to have to go around putting in version flags in every place this switch happens. I just want to do it once at compile time and be done with it.

Let me see if I got this correct, because I also do not understand how this could not be done just as good with versioning. You said you don't want to put "version flags in every place this switch happens". Did you mean every place that uses/imports the Camera module? Why not just have the Camera module change implementations according to the version (like Chris mentioned) ? Something like: ---- engine/gx/camera/Camera.d ---- module engine.gx.camera.Camera version(OGL) { // OGL implementation } else version(D3D) { // D3D implementation } ---- ---- -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 18 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Bruno Medeiros wrote:
 Daniel Keep wrote:
 And don't say "just use version()s" since I really don't want to have to
 go around putting in version flags in every place this switch happens.
 I just want to do it once at compile time and be done with it.

Let me see if I got this correct, because I also do not understand how this could not be done just as good with versioning. You said you don't want to put "version flags in every place this switch happens". Did you mean every place that uses/imports the Camera module? Why not just have the Camera module change implementations according to the version (like Chris mentioned) ? Something like: ---- engine/gx/camera/Camera.d ---- module engine.gx.camera.Camera version(OGL) { // OGL implementation } else version(D3D) { // D3D implementation } ---- ----

Because the plan is to eventually move to DDL. Once I do that, I have to go back and remove all of the version statements (that I didn't need to put there in the first place), since linking will then be done at runtime. For now, I'm just using dmd to do DDL's job at compile time. Also, I'm a damn stubborn bastard about these things: I've found a way that works for me and I'll be damned if we lets anyone take it away from usss, my precioussss! :P -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
May 18 2007
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Daniel Keep wrote:
 
 Bruno Medeiros wrote:
 Daniel Keep wrote:
 And don't say "just use version()s" since I really don't want to have to
 go around putting in version flags in every place this switch happens.
 I just want to do it once at compile time and be done with it.

this could not be done just as good with versioning. You said you don't want to put "version flags in every place this switch happens". Did you mean every place that uses/imports the Camera module? Why not just have the Camera module change implementations according to the version (like Chris mentioned) ? Something like: ---- engine/gx/camera/Camera.d ---- module engine.gx.camera.Camera version(OGL) { // OGL implementation } else version(D3D) { // D3D implementation } ---- ----

Because the plan is to eventually move to DDL. Once I do that, I have to go back and remove all of the version statements (that I didn't need to put there in the first place), since linking will then be done at runtime. For now, I'm just using dmd to do DDL's job at compile time. Also, I'm a damn stubborn bastard about these things: I've found a way that works for me and I'll be damned if we lets anyone take it away from usss, my precioussss! :P -- Daniel

I still don't see (as in, I dont' see) why one would need multiple version statements for your case. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 22 2007
prev sibling next sibling parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Ary Manzana wrote

 totaly unnecessary to have the module declaration
 say something different

Can you prove this statement correct? Why then have module declarations at all? What is the redundany good for? In general: any proof that some form of existing freedom is not usable is a counter argument for the wish to delete that freedom. For a freedom that is usable a declaration of unnecessity is insufficient; a retraction has to be grounded by greater wealth (in terms of money) of the set of possible users---unless it is a "political" decision. -manfred
May 12 2007
parent Derek Parnell <derek psych.ward> writes:
On Sun, 13 May 2007 05:22:15 +0000 (UTC), Manfred Nowak wrote:

 Ary Manzana wrote
 
 totaly unnecessary to have the module declaration
 say something different

Can you prove this statement correct? Why then have module declarations at all? What is the redundany good for? In general: any proof that some form of existing freedom is not usable is a counter argument for the wish to delete that freedom. For a freedom that is usable a declaration of unnecessity is insufficient; a retraction has to be grounded by greater wealth (in terms of money) of the set of possible users---unless it is a "political" decision.

The only reason I can see as the purpose of the module statement is to ensure that one has named the file as one intended it to be named. -- Derek Parnell Melbourne, Australia "Justice for David Hicks!" skype: derek.j.parnell
May 13 2007
prev sibling parent Ary Manzana <ary esperanto.org.ar> writes:
Thanks for all your answers.

I'll follow Daniel's advice.

Ary Manzana escribió:
 Manfred Nowak escribió:
 Ary Manzana wrote

 Why use an alternative of the built-in version system?

The version system is not equivalent to the module naming system.

Ok. My point is that it is totaly unnecessary to have the module declaration say something different than it's location relative to the include source path. This is like things work in Java, for example: you get an error if the package declaration and the filesystem dosen't match. Why not apply the same in D?

May 13 2007
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Manfred Nowak wrote:
 Ary Manzana wrote
 
 Why use an alternative of the built-in version system?

The version system is not equivalent to the module naming system. -manfred

That particular usage of the module system is equivalent to using the versioning system. Equivalent in the sense that they're both trying to do conditional compilation. However the version system was specifically designed to do that, whereas that module system usage is an ugly hack. (also see my reply to Daniel Keep) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 18 2007
prev sibling parent reply Sean Kelly <sean f4.ca> writes:
Ary Manzana wrote:
 
 Shouldn't the compiler say "Wait, you are saying that module one is in 
 file main.d, module two is in other.d and module lala.la is in 
 dir/some_other.d, this isn't quite well"?

I've decided that this is actually a good thing. It allows large modules to be split across multiple files and for different implementation files to be chosen at compile time when using the header/source model. It's also the only way I've found to compile the implementation of "object.d" for Tango. Actually naming it "object.d" caused all sorts of problems. Sean
May 22 2007
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Sean Kelly wrote:
 Ary Manzana wrote:
 Shouldn't the compiler say "Wait, you are saying that module one is in 
 file main.d, module two is in other.d and module lala.la is in 
 dir/some_other.d, this isn't quite well"?

I've decided that this is actually a good thing. It allows large modules to be split across multiple files and for different implementation files to be chosen at compile time when using the header/source model. It's also the only way I've found to compile the implementation of "object.d" for Tango. Actually naming it "object.d" caused all sorts of problems. Sean

But: A) "It allows large modules to be split across multiple files" What do you mean? Splitting a large module into multiple files implies putting each new file in a different module. What does that have to do with allowing module-file name mismatches? B) "and for different implementation files to be chosen at compile time when using the header/source model." And why is that a good thing? If I use conditional compilation and define conditional properties at compile time I achieve the same effect. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
May 26 2007
parent reply gareis <dhasenan gmail.com> writes:
== Quote from Bruno Medeiros (brunodomedeiros+spam com.gmail)'s article
 Sean Kelly wrote:
 Ary Manzana wrote:
 Shouldn't the compiler say "Wait, you are saying that module one is in
 file main.d, module two is in other.d and module lala.la is in
 dir/some_other.d, this isn't quite well"?

I've decided that this is actually a good thing. It allows large modules to be split across multiple files and for different implementation files to be chosen at compile time when using the header/source model. It's also the only way I've found to compile the implementation of "object.d" for Tango. Actually naming it "object.d" caused all sorts of problems. Sean

A) "It allows large modules to be split across multiple files" What do you mean? Splitting a large module into multiple files implies putting each new file in a different module. What does that have to do with allowing module-file name mismatches?

The first part is mostly naming convention. Though if you can't possibly imagine using one file without having the exact source of another file, they should be one module. You could combine the files, but that tends to work poorly after a while. Still, I'd use imports most of the time, if it were possible. For the second part, Mr. Kelly gave an example: his object module couldn't appear in object.d without causing issues.
 B) "and for different implementation files to be chosen at compile time
 when using the header/source model."
 And why is that a good thing? If I use conditional compilation and
 define conditional properties at compile time I achieve the same effect.

You can wrap your entire file in version statements, but then it's difficult to work with. If you have multiple people working on the functions for different versions, you might get conflicts with cvs / subversion / what-have-you (especially with coding style and editor issues). And IDEs might barf on entire functions wrapped in version statements and appearing multiple times. You could wrap all the import statements in version statements, but that's ugly and doesn't scale that well. Modules that aren't platform-specific or feature-specific will end up having to pay attention to platforms and features. You could have a module that just has a bunch of statements like: --- version (Windows) import foo.windows; version (Linux) { version (Bigendian) { import foo.linux_bigendian; } else { import foo.linux_little_endian; } version (UsingSSL) import foo.linux_ssl; } --- That's also annoying. And contrived. Still, if you're using makefiles and autotools, conditional compilation of files is the easiest way to go. You can compile each file into a separate object file for faster recompilation in the face of changes, and you don't have any issues with, for instance, foo.windows panicking because it can't use Windows functions on Linux. I'm not sure whether dsss allows for this sort of thing -- a source file that will not be used on one system and will not compile on it, but will be used on another system and compile on it.
May 26 2007
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Sorry for the long delay in this posts.

gareis wrote:
 == Quote from Bruno Medeiros (brunodomedeiros+spam com.gmail)'s article
 Sean Kelly wrote:
 Ary Manzana wrote:
 Shouldn't the compiler say "Wait, you are saying that module one is in
 file main.d, module two is in other.d and module lala.la is in
 dir/some_other.d, this isn't quite well"?

modules to be split across multiple files and for different implementation files to be chosen at compile time when using the header/source model. It's also the only way I've found to compile the implementation of "object.d" for Tango. Actually naming it "object.d" caused all sorts of problems. Sean

A) "It allows large modules to be split across multiple files" What do you mean? Splitting a large module into multiple files implies putting each new file in a different module. What does that have to do with allowing module-file name mismatches?

The first part is mostly naming convention. Though if you can't possibly imagine using one file without having the exact source of another file, they should be one module. You could combine the files, but that tends to work poorly after a while. Still, I'd use imports most of the time, if it were possible. For the second part, Mr. Kelly gave an example: his object module couldn't appear in object.d without causing issues.

Yes, the object module example is a valid use case for this behavior. But it is a very special case (hell, it's *unique*), which doesn't by itself justify module-file name mismatches.
 B) "and for different implementation files to be chosen at compile time
 when using the header/source model."
 And why is that a good thing? If I use conditional compilation and
 define conditional properties at compile time I achieve the same effect.

You can wrap your entire file in version statements, but then it's difficult to work with. If you have multiple people working on the functions for different versions, you might get conflicts with cvs / subversion / what-have-you (especially with coding style and editor issues). And IDEs might barf on entire functions wrapped in version statements and appearing multiple times.

Yes, that is not a good solution.
 You could wrap all the import statements in version statements, but that's ugly
 and doesn't scale that well. Modules that aren't platform-specific or
 feature-specific will end up having to pay attention to platforms and features.
 

Yes, that is not a good solution either.
 You could have a module that just has a bunch of statements like:
 ---
 version (Windows) import foo.windows;
 version (Linux) {
    version (Bigendian) {
       import foo.linux_bigendian;
    } else {
       import foo.linux_little_endian;
    }
    version (UsingSSL) import foo.linux_ssl;
 }
 ---
 
 That's also annoying. And contrived.
 

Like I said before, that is the alternative that I was thinking, and I don't see what's bad with it. Why is it annoying and contrived? The only issue I see is the one you mention below:
 Still, if you're using makefiles and autotools, conditional compilation of
files
 is the easiest way to go. You can compile each file into a separate object file
 for faster recompilation in the face of changes, and you don't have any issues
 with, for instance, foo.windows panicking because it can't use Windows
functions
 on Linux.
 

Indeed, you would need to specify to the build tool (or IDE) that certain modules (like the windows one on linux) are not to be compiled. But you have to the same thing with makefiles and autotools, so you're not any worse. In fact, a smart IDE (or build tool with semantic knowledge) might understand the version statements and automatically know which modules to compile or not. But if you're still not convinced, there is perhaps another alternative. Use different files for different implementations, but put each file on a different source folder, thus allowing each file to correctly match the pack+module names to the directory+file structure: --- src-linux/foo/bar.d --- module foo.bar; ... --- src-windows/foo/bar.d --- module foo.bar; ... ---- This is how it's done on Java programs with platform specific code(like SWT), and should work fine for D *and* be IDE-friendly. This should be adequate for big conditional variants, like platform, but no so much for small optional features, but you can always use a combination of methods for the cases where its not adequate. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Jun 01 2007