Whole source-tree statefull preprocessing, notion of a whole program

Vladimir Panteleev via Digitalmars-d digitalmars-d at puremagic.com
Sat Apr 8 10:57:11 PDT 2017


On Saturday, 8 April 2017 at 14:20:49 UTC, Boris-Barboris wrote:
>> Looks like your current implementation does not go in that 
>> direction, seeing as it uses properties for field access.
>
> Am i mistaken in assumption that such simple getter property 
> will be optimized to direct field access? Anyways, that's minor 
> detail.

I don't know the type of CONF.root, but from the usage syntax in 
your example, it looks like an associative array. Associative 
array lookup will be slower than simply accessing a variable.

>> Individual components' configuration can be delegated to their 
>> components; their modules could contain public struct 
>> definitions that you can add to the global Config struct, 
>> which describes the configuration of the entire application. 
>> I've used this pattern successfully in some projects, incl. 
>> Digger: 
>> https://github.com/CyberShadow/Digger/blob/master/config.d#L31-L36
>
> Ok, that's nice, but it still requires manual inclusion of such 
> field into global config struct.

Yes; in my opinion, I think that's desirable because it is 
aligned with the unidirectional flow of information from 
higher-level components to lower-level ones, and does not impose 
a particular configuration framework onto the lower-level 
components (they only need to declare their configuration in 
terms of a POD type).

> Some "compile-time callback" system still would scale better in 
> my opinion.

A similar effect can be achieved by allowing components to 
register themselves in a static constructor (not at compile-time, 
but at program start-up).

>> I understand that you seem to be looking for a way to change 
>> types (definitions in general) inside modules you import. This 
>> is problematic from several aspects, such as other modules 
>> depending on that module may find that the definitions "change 
>> under their feet".
>
> As expected since class that allows itself to be modified in 
> compile-time, always does so explicitly via mixin. Most of the 
> times such manipulation is used to extend functionality (add 
> field, plugin, method) without removing or modifying existing 
> ones. And if the names conflict, we get nice compile-time error 
> anyways.

Then you have problems such as the instance size of a class 
changing depending on whether the code that requires the instance 
size is seen by the compiler before the code that modifies the 
instance size. I think it would cause complicated design problems 
that limit the scalability of the language. Even without such 
features, DMD had to go through a number of bugs to iron out the 
correct semantics of evaluating types (e.g. with 
"typeof(this).sizeof" inside a struct declaration, or recursive 
struct template instantiations).

>> In D, once a type is declared and its final curly brace is 
>> closed, you will know that its definition will remain the same 
>> from anywhere in the program.
>
> That's kinda my point - definition needs to stay the same 
> because it's built by compiler as many times as there are 
> transtaltion units, because evil old C grandpa.

I think this is not about technical limitations, but intentional 
design choices. Allowing types to be modified post-declaration 
invalidates many contracts and assumptions that code may have, 
and make it harder to reason about the program as a whole. 
Compare with e.g. INTERCAL's COMEFROM instruction.

>> D's answer to partial classes is UFCS, however this does not 
>> allow "adding" fields, only methods.
>
> Adding fields, or, generally, objects \ collections of objects, 
> is the main use case. Adding methods in my experience is rare 
> scenario.

UFCS is widely used in D for component programming:

http://www.drdobbs.com/architecture-and-design/component-programming-in-d/240008321



More information about the Digitalmars-d mailing list