Ways of building the code

Programming, for all ages and all languages.
zloba

Re:Ways of building the code

Post by zloba »

2 AR:
You completely missed the point here, the point is not that C++ code can be built with a C compiler but that C code can be built with a C++ compiler.
That's exactly what I was saying. Did I say that old prototype handling should be removed?
You do realise that that is similar to the point of the D language.
I do. I know about the D language. I've read their reasoning, and I agree with some points and methods, but not all of them.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Ways of building the code

Post by Colonel Kernel »

My real gripe with headers and prototypes in C++ is the lack of expressiveness in terms of visibility of classes. Basically a class is either public (declared in the headers) or private (declared in a source file, perhaps in an anonymous namespace) from the point of view of the lib or executable it's compiled into. At least in Java and C# there is the concept of "internal" or "package" classes. Trying to emulate that by using a convention in C++ can get messy (e.g. -- put the "public" headers for <component> in inc/<subsystem>/<component>, put the "private" headers in src/<subsystem>/<component> and put the "internal" headers in src/<subsystem>/inc/<component>). :P
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
zloba

Re:Ways of building the code

Post by zloba »

the lack of expressiveness in terms of visibility of classes
ditto. Not sure if it's the same as what you said, but..
It would be nice if classes' public interfaces could be exposed in the headers without also having to stick there all the implementation details, member variables, etc. Having these things in the headers is bad, because implementation details may bring unwanted dependencies (types of member variables, APIs used in the bodies) into the user code, whether or not they are declared private..

If they could be enclosed in a "black box", with only public stuff sticking out..

I've been using abstract base classes (interfaces) and instantiation functions in headers, everything else in implementation source files. That also allows to implement method bodies in-place. (not advocating anything here, just FYI)
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Ways of building the code

Post by Solar »

Or make duplicating a prototype optional.
In C89, it is. You can use a function that has never been declared. It gives a compiler warning, but it works.

In C++ (and IIRC C99), this feature has been abandoned for stricter type checking, generally welcomed as A Good Thing (TM).
Are you saying that existing languages are final and that no new ones should be created?
I say that existing languages exist, and if you want to change them, go talk to the standard committee. Of course new ones should be created, but it doesn't do saying "if only C++ would..." or "if only C had...".
It is intended to replace C/C++ and to be as practical (more so), barring immediate compatibility and general acceptance.
Don't be too surprised if you get nowhere. The term "better" isn't only about technical merit. It does, among other things, include compatibility and acceptance.

I would be among the last people claiming that C++ is a "perfect" language. Far from it, it is about the ugliest language around that's still for real. (Barring perhaps Perl, Assembler, and Brainfuck.)

But it does its job, there are good compilers readily available, books and tutorials and tools and helpful people... all this makes this ugly butt of a language into something extremly useful.

You have to get a lot of technical merit to beat that...
New OS, new language, new everything.
Yep. We discussed that, too. The thing is, if you think that to its logical end, you'd need new CPUs on new mainboards using new protocols, too. At some point, you have to give in to "prior art". I prefered being able to ask other people what's wrong with my (C/C++) code, and get a response. Your mileage may vary.
At least in Java and C# there is the concept of "internal" or "package" classes. Trying to emulate that by using a convention in C++ can get messy.
Why would you want to emulate Java / C# behaviour in C++? C++ has no concept of a "package". If you're trying to "emulate" that, you're trying to write Java, not C++. Being the maintenance coder I am, I hear all alarm bells going off when I see someone using X constructs in language Y, because that usually means that person isn't really fluent in Y and its concepts.
...put the "public" headers for <component> in inc/<subsystem>/<component>, put the "private" headers in src/<subsystem>/<component> and put the "internal" headers in src/<subsystem>/inc/<component>
Put the "public" headers in /project/headers/<component>/ and the "private" headers in /project/<component>/. Add /project/headers/ to your compiler's include path (-I option). Use [tt]#include <component/xyz.h>[/tt] for public headers and [tt]#include "xyz.h"[/tt] for private headers.
Every good solution is obvious once you've found it.
zloba

Re:Ways of building the code

Post by zloba »

go talk to the standard committee.
Somehow I doubt that will accomplish anything. There are people on the standards committees that are so much more influential than me as makes no difference. I'm a nobody, and a noob at that, even compared to most people here. (not that I'm complaining :) )
Don't be too surprised if you get nowhere. (about replacing C++)
That depends on where I'm going, no? I'm not by any means counting on any sort of popularity, not now, at least. (Would be nice, but unlikely. Not with the current syntax.)
Right now, getting somewhere means making it basically usable and writing the OS and other things. Which is not so remote, it's mostly working and nearing alpha release.
But it does its job, there are good compilers readily available, books and tutorials and tools
I don't completely agree. While cleaning up my code to compile on Borland compiler, I had to fix little quirks all over. I gave up on Microsoft's compiler a long time ago, as it simply couldn't handle a certain thing (a known issue).
And what am I supposed to port to my OS, gcc? No thanks.
Tutorials can be written, tools provided, when it comes to releasing the language, if ever.

Part of my motivation is having a deterministically behaving compiler, simple and nice, ready to port to any platform. No luggage, no messy grammar, no compatibility APIs, etc.
(don't suggest Forth :) )
It should also be amenable to change, without breaking code.
if you think that to its logical end, you'd need new CPUs on new mainboards using new protocols, too.
Would be nice, but existing CPUs will have to do - I can make a compiler, not so with hardware.
Why would you want to emulate Java / C# behaviour in C++?
Because I want that kind of behaviour? What does it matter if a feature is associated with Java, C# or anything else? It's about the technique, it's usefulness and feasibility, and removing restrictions that are just there.
(Actually, there's not so much that I want from Java. C#, however, has made some progress in the right direction)
We discussed that, too.
Indeed we did. Now, a year has passed, and it's close to becoming a reality. I can replace C++ with my language in my BareBones-derived OS skeleton as soon as I bring the compiler to a stable state.
User avatar
Colonel Kernel
Member
Member
Posts: 1437
Joined: Tue Oct 17, 2006 6:06 pm
Location: Vancouver, BC, Canada
Contact:

Re:Ways of building the code

Post by Colonel Kernel »

Solar wrote:Why would you want to emulate Java / C# behaviour in C++? C++ has no concept of a "package". If you're trying to "emulate" that, you're trying to write Java, not C++. Being the maintenance coder I am, I hear all alarm bells going off when I see someone using X constructs in language Y, because that usually means that person isn't really fluent in Y and its concepts.
I'm not trying to apply one language's construct to another. I'm comparing the ability of several languages to handle a higher-level design construct -- that of sub-components of a component that have more visibility between each other than the outside world has access to. This is a perfectly valid thing to want in a good OO design IMO. My point was that Java and C# both make this a first-class language feature while C++ does not.

When I program in C, I still write OO code, even though the language doesn't support objects as a first-class feature. I consider this to be a reasonable approach, albeit clumsy. My beef about C++ and class visibility is the same kind of thing. Just as C isn't inherently object-oriented, I would argue that C++ isn't inherently component-oriented.
Put the "public" headers in /project/headers/<component>/ and the "private" headers in /project/<component>/. Add /project/headers/ to your compiler's include path (-I option). Use [tt]#include <component/xyz.h>[/tt] for public headers and [tt]#include "xyz.h"[/tt] for private headers.
Yes, that works, but it's only a two-level scheme. It isn't possible to selectively provide component B with some of component A's non-public interfaces -- it's all or nothing.
Top three reasons why my OS project died:
  1. Too much overtime at work
  2. Got married
  3. My brain got stuck in an infinite loop while trying to design the memory manager
Don't let this happen to you!
AR

Re:Ways of building the code

Post by AR »

zloba wrote: It would be nice if classes' public interfaces could be exposed in the headers without also having to stick there all the implementation details, member variables, etc. Having these things in the headers is bad, because implementation details may bring unwanted dependencies (types of member variables, APIs used in the bodies) into the user code, whether or not they are declared private..

If they could be enclosed in a "black box", with only public stuff sticking out..
You appear to have missed the reasoning for this, the variables are declared in the declaration so that malloc knows how much memory to allocate, you could just replace "int var1; int var2;" with "char variablesize[8];" but I don't consider that an elegant solution, not to mention variable size dependant. Dependencies are concealed by simply leaving off the member variables in public headers then creating a "CreateMyClassInstance()" which new's the class internally so that a program using the library won't be dependant on the classes size.

And no C# does not actually conceal this stuff, everything is still revealed in the metadata, this is the reason why it doesn't require prototypes and headers, why inheritance works without the original prototype and so forth (and how malloc knows how much memory to get for a C# class since the member variables are visible to the runtime compiler). It should be entirely possible to implement metadata in C++ to get all the "good" features (reflection, no need for prototypes, advanced type safety, etc) not that I would particularly want to try. [Microsoft already did this with "Managed C++" so it is clearly possible]
zloba

Re:Ways of building the code

Post by zloba »

You appear to have missed the reasoning for this, the variables are declared in the declaration so that malloc knows how much memory to allocate,
No, I didn't miss it.
you could just replace "int var1; int var2;" with "char variablesize[8];" but I don't consider that an elegant solution, not to mention variable size dependant
I completely agree.
Dependencies are concealed by simply leaving off the member variables in public headers then creating a "CreateMyClassInstance()" which new's the class internally so that a program using the library won't be dependant on the classes size.
Isn't that exactly what I said I've been doing, in the same post?
It should be entirely possible to implement metadata in C++ to get all the "good" features (reflection, no need for prototypes, advanced type safety, etc) not that I would particularly want to try.
Indeed.
OSMAN

Re:Ways of building the code

Post by OSMAN »

The way I was talking about is working fine for me, because I don't have to change anything from makefile or other files when I add new c-files to my kernel. And I don't mind even it does take the whole compilation if I change a part of the code, (because the compilation takes less than 2 seconds.)

I'd just like to have more comments on this way.
(PS. I'm not using C++)
zloba

Re:Ways of building the code

Post by zloba »

2 OSMAN
The way I was talking about is working fine for me ...
I think you just answered your own question. As long as it works for you and your style, and you know the alternative (separate compilation), in case you ever need it..

Btw, why not just #include all .c files from one, say main.c ? Is your method different, how do you do it?

What I'm getting at, if you just concatenate all files together, and there's an error message with a line number, how will you know the line number in the original files?
OSMAN

Re:Ways of building the code

Post by OSMAN »

Hi.
I just use $ cat functions.h *.h *.c main.c > fullkernel.c
I see the correct number of lines for the error messages from fullkernel.c.
With this way I don't need #includes indeed!
I just wanted to know if you knew something broken in it.
User avatar
Solar
Member
Member
Posts: 7615
Joined: Thu Nov 16, 2006 12:01 pm
Location: Germany
Contact:

Re:Ways of building the code

Post by Solar »

OSMAN wrote: I just use $ cat functions.h *.h *.c main.c > fullkernel.c
functions.h and main.c will be included twice. Assuming that main.c holds a function named main(), that function will be defined twice, which should result in a compiler error. Same goes for any definition done in functions.h.

Your headers cannot use anything declared in another header, unless that header is earlier in the sorting done by the shell you happen to use, or you declare everything in functions.h - that would introduce just the redundancy you seem intent to avoid, and probably result in many more compiler warnings unless you use header guards - you'll have a hard time explaining anyone why he should use a precaution against multiple inclusion if you go to such lengths to avoid using #include...
I see the correct number of lines for the error messages from fullkernel.c.
You still have to figure out which file you have to edit, because you cannot edit fullkernel.c - that will be overwritten next time you run that command.
I just wanted to know if you knew something broken in it.
More than I can fit in a single post. Please don't take this personally, but I consider the above an ugly perversion of C concepts.

And as soon as you start writing anything remotely resembling a link library, you will want to use seperate compilation units anyway, unless you want every single application to add the complete link library to its binary if it uses but a single function from it...
Every good solution is obvious once you've found it.
zloba

Re:Ways of building the code

Post by zloba »

With this way I don't need #includes indeed!
Why are you avoiding #includes, what's wrong with them?

#inlcude does the job, and does it better - it also generates special directives which tell the compiler from which file a given chunk of code came!
(Sure you can make a script that will also produce those directives to identify the actual source file, but.. what's the point?)
I just wanted to know if you knew something broken in it.
Having error messages refer to locations in a generated file - I consider that "something broken", for one. Having to concatenate every single file used, that's another. Not being able to plug in a different project as a library and a header, that's another, as Solar said.

Why?
Schol-R-LEA

Re:Ways of building the code

Post by Schol-R-LEA »

Piece of advice, Zloba? Don't try to replace C++; you'll only end up driving yourself nuts, trying to second-guess every other programmer on the planet. If you want to write a new language, write the one you want to use, and use it.

One of the truisms of the trade is that every truly great program came out of one programmer who said, "This is what I want, and to hell with everyone else." While it's not quite true - things like the Internet would have been impossible if it were - it certainly has been true for many things. Unix started out when Dennis Ritchie needed a programming environment to write a video game in. C was Brian Kernighan's way of getting around the things that bugged him in BCPL; C++, in turn, was just a filter that let Bjorne Soustroup write Simula-like programs in C when he needed to do some simulations. Lisp s-expressions were just a clever way of avoiding having to write a full-blown compiler (in an era when compiler-writing was still black magic). Building the Apple I was Woz's idea of a fun way to spend a weekend. None of them set out to conquer the world, yet they succeeded far beyond their goals.

Lisp evangelist Paul Graham wrote an extensive essay on what makes languages popular, and one thing he pointed out was that the really successful languages - C, Perl, the early Lisps - were ones the programmers had fun programming in. They could hack. They could improvise. They could do what they wanted without the language and the environment getting in the way. The reason they got that way was because the programmer who came up with it was having fun with it, and then decided to share it with some friends. They always spread from the grassroots, not from some big plan to take over the world.

In other words, if you aren't having fun doing it, and you won't getting paid for it, you probably shouldn't bother.

I could be wrong, of course; people have all kinds of motivations for doing things. Eris knows I've been through the fire-in-the-belly stage myself. But I think in the end that setting out to topple x - whether x is 'Windows', 'C++', 'Linux' or whatever - is probably not going to accomplish much. Chill out. If you create something really amazing, people will come to you. And if it doesn't set the world on fire, well, how many things do?
OSMAN

Re:Ways of building the code

Post by OSMAN »

I should have been more specific with the filenames:
cat ./main/functions.c ./headers/*.h ./oslib/*.c ./main/main.c > fullkernel.c
So, nothing will be included twice.

And what I have against #includes is that always I create a new source file I should write an #include for it to some other file, and so on. I think I will use #includes when I have a grand plan of what my system is going to be like (;at the moment I haven't).

(And sorry if my way breaks the rules, but it works, and that's great for me to get something working that I've found out!)
Post Reply