Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.misc > #2178 > unrolled thread

A good subset of C

Started by"James Harris" <james.harris.1@gmail.com>
First post2014-05-05 08:47 +0100
Last post2014-05-05 19:08 -0500
Articles 20 on this page of 64 — 9 participants

Back to article view | Back to comp.lang.misc


Contents

  A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-05 08:47 +0100
    Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-05 10:56 +0100
      Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-05 19:41 +0100
        Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-05 21:08 +0100
          Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-05 21:58 +0100
            Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-05 22:55 +0100
              Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-06 00:01 +0100
                Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-06 00:44 +0100
            Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-06 09:45 +0100
    Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-05 07:33 -0400
      Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-05 19:14 +0100
      Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-05 20:12 +0100
        Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-05 18:57 -0400
          Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-07 11:55 +0100
            Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-07 19:04 -0400
              Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-08 10:14 +0100
                Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-08 07:35 -0400
                  Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-08 16:22 +0100
                    Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-09 16:45 -0400
                      Re: A good subset of C "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-10 09:04 +0200
                        Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-10 16:30 -0400
                          Re: A good subset of C "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-11 11:59 +0200
                            Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-11 11:06 -0400
                              Re: A good subset of C Kaz Kylheku <kaz@kylheku.com> - 2014-05-12 00:26 +0000
                              Re: A good subset of C "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de> - 2014-05-12 09:54 +0200
                                Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-12 20:01 -0400
                              Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-14 17:45 +0100
                                Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-14 18:11 -0400
                                  Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-14 23:54 +0100
                                    Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-14 19:43 -0400
                                      Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-17 18:00 +0100
                                        Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-17 16:00 -0400
                                          Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-17 22:17 +0100
                                            Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-17 19:58 -0400
                                              Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-18 07:59 +0100
                                                Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-18 13:10 -0400
                                                  Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-19 00:54 +0100
                                    Re: A good subset of C Andy Walker <news@cuboid.co.uk> - 2014-05-15 01:31 +0100
                                      Re: A good subset of C BGB <cr88192@hotmail.com> - 2014-05-14 23:43 -0500
                                    Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-17 18:38 +0100
                                  Re: A good subset of C Ian Collins <ian-news@hotmail.com> - 2014-05-25 11:04 +1200
                                    Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-24 20:36 -0400
                                      Re: A good subset of C Ian Collins <ian-news@hotmail.com> - 2014-05-25 12:53 +1200
                                        Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-24 21:34 -0400
                                          Re: A good subset of C Ian Collins <ian-news@hotmail.com> - 2014-05-25 14:11 +1200
                                          Re: A good subset of C Kaz Kylheku <kaz@kylheku.com> - 2014-05-25 06:47 +0000
                                      Re: A good subset of C Kaz Kylheku <kaz@kylheku.com> - 2014-05-25 06:43 +0000
    Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-05 20:59 +0100
      Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-05 22:28 +0100
        Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-05 18:57 -0400
          Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-06 00:26 +0100
        Re: A good subset of C George Neuner <gneuner2@comcast.net> - 2014-05-06 14:21 -0400
          Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-07 15:43 +0100
            Re: A good subset of C George Neuner <gneuner2@comcast.net> - 2014-05-07 16:03 -0400
              Re: A good subset of C "BartC" <bc@freeuk.com> - 2014-05-07 21:31 +0100
            Re: A good subset of C BGB <cr88192@hotmail.com> - 2014-05-07 15:41 -0500
      Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-05 18:46 -0400
        Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-06 00:42 +0100
          Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-06 06:48 -0400
            Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-07 15:40 +0100
              Re: A good subset of C "Rod Pemberton" <dont_use_email@xnothavet.cqm> - 2014-05-08 06:50 -0400
                Re: A good subset of C "James Harris" <james.harris.1@gmail.com> - 2014-05-08 15:43 +0100
                  Re: A good subset of C George Neuner <gneuner2@comcast.net> - 2014-05-08 14:41 -0400
    Re: A good subset of C BGB <cr88192@hotmail.com> - 2014-05-05 19:08 -0500

Page 1 of 4  [1] 2 3 4  Next page →


#2178 — A good subset of C

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-05 08:47 +0100
SubjectA good subset of C
Message-ID<lk7flm$m95$1@dont-email.me>
In two recent threads we discussed good and bad points about C. Some good 
things were mentioned but the focus was mainly on the points that we would 
like to fix. I got to wondering if there could be considered a "good" subset 
of C - i.e. of the whole programming approach including language, 
preprocessor, standard library etc.

The subset should be much easier to compile than full C but it does not need 
to do everything that a programming language should; things could be added.

Put another way, if you were designing a new language based on C what parts 
of C would you keep in?

James

[toc] | [next] | [standalone]


#2181

From"BartC" <bc@freeuk.com>
Date2014-05-05 10:56 +0100
Message-ID<XfJ9v.209855$X41.111305@fx15.am4>
In reply to#2178
"James Harris" <james.harris.1@gmail.com> wrote in message 
news:lk7flm$m95$1@dont-email.me...

> I got to wondering if there could be considered a "good" subset of C - 
> i.e. of the whole programming approach including language, preprocessor, 
> standard library etc.
>
> The subset should be much easier to compile than full C but it does not 
> need to do everything that a programming language should; things could be 
> added.

That depends on your aims for the subset. If any sort of compatibility with 
the vast range of existing C sources is needed, then your hands are pretty 
much tied and you will have to leave nearly everything in (ie. just 
re-implement another C compiler).

For example, if you wanted to be able to just write #include <windows.h> or 
#include <stdafx.h> in the new language, or make use of any third party 
libraries where normally you'd just include a bunch of headers, then I can't 
see any new language in managing to be much different. A few additions 
perhaps, but then it would be a superset (and not a simple project either).

If you are only going to write new programs, then you can probably get away 
with leaving out troublesome features; most of the macro pre-processor for 
example (which I think this has had a negative influence on the language).

> Put another way, if you were designing a new language based on C what 
> parts of C would you keep in?

For a language at the same level, then the basics are going to be the same, 
in terms of data-types, statements and expressions. But every language is 
going to have these; what unique features does C have that you want to 
replicate? Probably not many!

(Actually, I've adopted a few minor features from C over the years, some of 
which I'd disliked at first:

* '0x123' style for hex numbers
* '()' to indicate a function call with no parameters
*  I might adopt auto-derefs for function names and array accesses
* Using anonymous structs and unions to control layout in structs (instead 
of explicit offsets)
* I'm thinking of having case-sensitive identifiers
* And having separate treatment of statements and expressions (previously 
these were treated the same; it's better to have them distinct, even though 
gcc has an extension to mix them up again!))

-- 
Bartc
 

[toc] | [prev] | [next] | [standalone]


#2186

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-05 19:41 +0100
Message-ID<lk8m0i$acg$1@dont-email.me>
In reply to#2181
"BartC" <bc@freeuk.com> wrote in message 
news:XfJ9v.209855$X41.111305@fx15.am4...
> "James Harris" <james.harris.1@gmail.com> wrote in message 
> news:lk7flm$m95$1@dont-email.me...
>
>> I got to wondering if there could be considered a "good" subset of C - 
>> i.e. of the whole programming approach including language, preprocessor, 
>> standard library etc.
>>
>> The subset should be much easier to compile than full C but it does not 
>> need to do everything that a programming language should; things could be 
>> added.
>
> That depends on your aims for the subset. If any sort of compatibility 
> with the vast range of existing C sources is needed, then your hands are 
> pretty much tied and you will have to leave nearly everything in (ie. just 
> re-implement another C compiler).

I wasn't thinking of compatibility with existing source code. As you say, 
that would just end up in having to do what any C compiler does.

> For example, if you wanted to be able to just write #include <windows.h> 
> or #include <stdafx.h> in the new language, or make use of any third party 
> libraries where normally you'd just include a bunch of headers, then I 
> can't see any new language in managing to be much different. A few 
> additions perhaps, but then it would be a superset (and not a simple 
> project either).
>
> If you are only going to write new programs, then you can probably get 
> away with leaving out troublesome features; most of the macro 
> pre-processor for example (which I think this has had a negative influence 
> on the language).

The preprocessor is a bit of an anomaly. Expressions like sizeof() would be 
useful but they cannot be used in the preprocessor as they are only valid 
later in the compilation. Could the most useful features of the preprocessor 
be integrated into the language? It might be better for the compiler to make 
additional passes. Then all of the syntax and data for a preprocessing-type 
step could be the same as that used in the compilation - possibly.

>> Put another way, if you were designing a new language based on C what 
>> parts of C would you keep in?
>
> For a language at the same level, then the basics are going to be the 
> same, in terms of data-types, statements and expressions. But every 
> language is going to have these; what unique features does C have that you 
> want to replicate? Probably not many!

That might be good. The simpler the better.

> (Actually, I've adopted a few minor features from C over the years, some 
> of which I'd disliked at first:
>
> * '0x123' style for hex numbers
> * '()' to indicate a function call with no parameters
> *  I might adopt auto-derefs for function names and array accesses

That doesn't sound like a big issue but I don't understand what you had in 
mind.

> * Using anonymous structs and unions to control layout in structs (instead 
> of explicit offsets)

Could you post a small example of that?

> * I'm thinking of having case-sensitive identifiers
> * And having separate treatment of statements and expressions (previously 
> these were treated the same; it's better to have them distinct, even 
> though gcc has an extension to mix them up again!))

Doesn't C treat statements as expressions anyway?

James

[toc] | [prev] | [next] | [standalone]


#2190

From"BartC" <bc@freeuk.com>
Date2014-05-05 21:08 +0100
Message-ID<2dS9v.221970$t73.184410@fx14.am4>
In reply to#2186
"James Harris" <james.harris.1@gmail.com> wrote in message
news:lk8m0i$acg$1@dont-email.me...
> "BartC" <bc@freeuk.com> wrote in message
> news:XfJ9v.209855$X41.111305@fx15.am4...

>> If you are only going to write new programs, then you can probably get
>> away with leaving out troublesome features; most of the macro
>> pre-processor for example (which I think this has had a negative
>> influence on the language).
>
> The preprocessor is a bit of an anomaly. Expressions like sizeof() would
> be useful but they cannot be used in the preprocessor as they are only
> valid later in the compilation. Could the most useful features of the
> preprocessor be integrated into the language? It might be better for the
> compiler to make additional passes. Then all of the syntax and data for a
> preprocessing-type step could be the same as that used in the
> compilation - possibly.

I've done without a pre-processor for decades. But then I haven't needed to
create the same source code for lots of different systems and
configurations. Using it for such purposes doesn't generate the best-looking
source code however. It might be better to look at alternative approaches
for that.

I've always had simple text-substitution macros, but without parameters:

define tword = tu32             # create alias
define inta = (fullcmd.opnds[1])

These don't need a separate pass. But they have the usual problems of having
file-scope. I don't use them to define constants, there are proper
statements for those.

I have recently added conditional compilation, but only because I was
porting C-derived code that used it and it was easier to add it.

(There are few other directives that are used during tokenising, but they
don't really count as a 'preprocessor', such as include and strinclude
(which turns a file into a string constant).)

>> (Actually, I've adopted a few minor features from C over the years, some
>> of which I'd disliked at first:
>>
>> * '0x123' style for hex numbers
>> * '()' to indicate a function call with no parameters
>> *  I might adopt auto-derefs for function names and array accesses
>
> That doesn't sound like a big issue but I don't understand what you had in
> mind.

In C you can write fnptr(a,b,c) instead of (*fnptr)(a,b,c), and axptr[i]
instead of (*axptr)[i] (probably a good thing too because the parentheses
needed add clutter).

I currently have to write fnptr^(a,b,c) and axptr^[i]; not as bad as the C
would be, but there can be advantages in hiding the indirect nature of the
function or array pointers.

>> * Using anonymous structs and unions to control layout in structs
>> (instead of explicit offsets)
>
> Could you post a small example of that?

I used to write code like this:

type varrec = record
 word   tag
 byte   copy
 byte   alloc

    byte celemtype @alloc
    long tagx @tag
....

(Where word=16 bits, long=32 bits). This defines three fields totalling
32-bits, an alias for the 'alloc' field, and a way of accessing all 32-bits
at once using the 'tagx' field.

In C the above would be written like this:

typedef struct _varrec {
 union {
  struct {
   u16 tag;
   u8 copy;
   union {
    u8 alloc;
    u8 celemtype;
   };
 };
  u32 tagx;
 };

Actually, my version doesn't look too bad in comparison! But in order to
target C, it was easier to change to this style (than use various tricks,
type-punning etc, to achieve the same).

>> * I'm thinking of having case-sensitive identifiers
>> * And having separate treatment of statements and expressions (previously
>> these were treated the same; it's better to have them distinct, even
>> though gcc has an extension to mix them up again!))
>
> Doesn't C treat statements as expressions anyway?

I think you can write an expression where a statement might be (eg.
assignment or call), but not a statement where an expression is expected
(eg. fn(a,b,for(i=0;i<10;++i)).

But even this lets a few odd-looking constructs through; this is legal:

  a+b;

but is likely a mistake. By separating the two completely, it was much
easier to pick up errors (especially writing a=b instead of a:=b).

(Previously I really could write an entire program almost in place of a 
parameter or index, or on the left or right side of an assignment. It worked 
fine, but dropped it when I was experimenting with source-to-source 
translators (eg. having C or Python as output).

It makes for a more conventional language, but I haven't reinstated that and
haven't missed it.)

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#2192

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-05 21:58 +0100
Message-ID<lk8u1q$abe$1@dont-email.me>
In reply to#2190
"BartC" <bc@freeuk.com> wrote in message 
news:2dS9v.221970$t73.184410@fx14.am4...

...

>> The preprocessor is a bit of an anomaly. Expressions like sizeof() would
>> be useful but they cannot be used in the preprocessor as they are only
>> valid later in the compilation. Could the most useful features of the
>> preprocessor be integrated into the language? It might be better for the
>> compiler to make additional passes. Then all of the syntax and data for a
>> preprocessing-type step could be the same as that used in the
>> compilation - possibly.
>
> I've done without a pre-processor for decades. But then I haven't needed 
> to
> create the same source code for lots of different systems and
> configurations. Using it for such purposes doesn't generate the 
> best-looking
> source code however. It might be better to look at alternative approaches
> for that.

Source code that contains lots of #if ... #else ... #endif blocks can become 
hard to maintain. It is easy to 'patch' some code for different 
circumstances with conditional compilation but I'm not sure that as a 
solution it scales well.

What about the preprocessor's pulling in header files, though? Because C is 
a static language the compiler needs to know some things at compile time 
and, when interfacing with other pieces of code it is traditional for a 
header file to be created describing interface info about the other module. 
Do you have a different way to support separate compilation of modules that 
interface with each other?

...

>> Doesn't C treat statements as expressions anyway?
>
> I think you can write an expression where a statement might be (eg.
> assignment or call), but not a statement where an expression is expected
> (eg. fn(a,b,for(i=0;i<10;++i)).
>
> But even this lets a few odd-looking constructs through; this is legal:
>
>  a+b;
>
> but is likely a mistake. By separating the two completely, it was much
> easier to pick up errors (especially writing a=b instead of a:=b).

Yes.

  b()

is obviously OK but

  a + b()

is a bit odd. Of course, b has to be called because it might have an effect 
but the addition of a seems to be superfluous.

James

[toc] | [prev] | [next] | [standalone]


#2195

From"BartC" <bc@freeuk.com>
Date2014-05-05 22:55 +0100
Message-ID<8PT9v.293553$te5.172198@fx13.am4>
In reply to#2192
"James Harris" <james.harris.1@gmail.com> wrote in message
news:lk8u1q$abe$1@dont-email.me...
> "BartC" <bc@freeuk.com> wrote in message

>> I've done without a pre-processor for decades.

> What about the preprocessor's pulling in header files, though? Because C
> is a static language the compiler needs to know some things at compile
> time and, when interfacing with other pieces of code it is traditional for
> a header file to be created describing interface info about the other
> module. Do you have a different way to support separate compilation of
> modules that interface with each other?

I have an import system that I used for dynamic modules, and that worked
well. I've now tried to use it for static code. It doesn't work quite as
well, but well enough to keep it in (and considerably better than having to
mess around with C-style headers).

It works something like this. Suppose your source language is called A, and
file extensions are ".a". Then:

* In a source module lib.a, all names are local (non-exported) by default

* To export a name, you place 'global' in front of the declaration. This
applies to functions, types, variables, named constants and enums.

* When compiled, an automatic exports file is generated, called lib.ax,
containing the exported names in a source format than can be included by
another module.

* When another module, such as prog.a, needs to use module lib, you just
write:

  import lib

and this will automatically include the lib.ax file (You can also write
directly: 'include "lib.ax"', but that doesn't check whether lib has already
been processed as 'import lib' does.)

* Inside lib.ax, exported names are defined inside a block (importmodule lib
= ..declarations ... end) which also bestows the namespace 'lib' on these
names. But I don't use that much.

It sounds great, but there are a few problems:

* The module structure must form a hierarchy, which creates problems with
modules that mutually import from each other. This is good discipline in
getting your program structured neatly, but there are still a few
declarations that must done manually (and declared as external).

* The order of compilation can be critical; the module at the top of the
tree should be compiled first, when it changes. An IDE can sort this out, or
I just do a couple of 'compile-all' from time to time (each takes <2 seconds
on my largest project).

Since I usually only work on a small number of modules, most of the time 
it's not an issue.

>> But even this lets a few odd-looking constructs through; this is legal:
>>
>>  a+b;
>>
>> but is likely a mistake. By separating the two completely, it was much
>> easier to pick up errors (especially writing a=b instead of a:=b).
>
> Yes.
>
>  b()
>
> is obviously OK but
>
>  a + b()
>
> is a bit odd. Of course, b has to be called because it might have an
> effect but the addition of a seems to be superfluous.

I used to write code like this when I used an inline assembler a lot:

 a+b

would evaluate a+b and leave the result in EAX. It was handy! So I might 
have to stick a keyword in front to turn it into a statement:

 eval a+b

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#2199

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-06 00:01 +0100
Message-ID<lk959c$uag$1@dont-email.me>
In reply to#2195
"BartC" <bc@freeuk.com> wrote in message 
news:8PT9v.293553$te5.172198@fx13.am4...
> "James Harris" <james.harris.1@gmail.com> wrote in message
> news:lk8u1q$abe$1@dont-email.me...
>> "BartC" <bc@freeuk.com> wrote in message
>
>>> I've done without a pre-processor for decades.
>
>> What about the preprocessor's pulling in header files, though? Because C
>> is a static language the compiler needs to know some things at compile
>> time and, when interfacing with other pieces of code it is traditional 
>> for
>> a header file to be created describing interface info about the other
>> module. Do you have a different way to support separate compilation of
>> modules that interface with each other?
>
> I have an import system that I used for dynamic modules, and that worked
> well. I've now tried to use it for static code. It doesn't work quite as
> well, but well enough to keep it in (and considerably better than having 
> to
> mess around with C-style headers).
>
> It works something like this. Suppose your source language is called A, 
> and
> file extensions are ".a". Then:
>
> * In a source module lib.a, all names are local (non-exported) by default
>
> * To export a name, you place 'global' in front of the declaration. This
> applies to functions, types, variables, named constants and enums.
>
> * When compiled, an automatic exports file is generated, called lib.ax,
> containing the exported names in a source format than can be included by
> another module.
>
> * When another module, such as prog.a, needs to use module lib, you just
> write:
>
>  import lib
>
> and this will automatically include the lib.ax file (You can also write
> directly: 'include "lib.ax"', but that doesn't check whether lib has 
> already
> been processed as 'import lib' does.)
>
> * Inside lib.ax, exported names are defined inside a block (importmodule 
> lib
> = ..declarations ... end) which also bestows the namespace 'lib' on these
> names. But I don't use that much.
>
> It sounds great, but there are a few problems:

It does sound good, thanks. I think I can use something like that.

> * The module structure must form a hierarchy, which creates problems with
> modules that mutually import from each other. This is good discipline in
> getting your program structured neatly, but there are still a few
> declarations that must done manually (and declared as external).

I'm not sure that a hierarchy is needed. To make an example, say there were 
two source files, P.a and Q.a and each referred to exports from the other so 
that a hierarchy is impossible. Let's say we try to compile P first.

When the compiler is compiling P and sees an import referring to Q it could:

1. Check for a file Q.ax which is newer than Q.a. If there is not, scan Q.a 
for exports and build an up-to-date Q.ax without going through a full 
compile of Q.a.
2. Use Q.ax to compile P.a including preparing P.ax.

If and when the compiler is told to compile Q.a it goes through the same 
process but finds P.ax to be newer than P.a.

Would that work?

James

[toc] | [prev] | [next] | [standalone]


#2203

From"BartC" <bc@freeuk.com>
Date2014-05-06 00:44 +0100
Message-ID<UnV9v.259259$vB1.224540@fx36.am4>
In reply to#2199
"James Harris" <james.harris.1@gmail.com> wrote in message
news:lk959c$uag$1@dont-email.me...
> "BartC" <bc@freeuk.com> wrote in message

>> I have an import system that I used for dynamic modules, and that worked
>> well. I've now tried to use it for static code. It doesn't work quite as
>> well, but well enough to keep it in (and considerably better than having
>> to
>> mess around with C-style headers).

> It does sound good, thanks. I think I can use something like that.
>
>> * The module structure must form a hierarchy, which creates problems with
>> modules that mutually import from each other. This is good discipline in
>> getting your program structured neatly, but there are still a few
>> declarations that must done manually (and declared as external).
>
> I'm not sure that a hierarchy is needed. To make an example, say there
> were two source files, P.a and Q.a and each referred to exports from the
> other so that a hierarchy is impossible. Let's say we try to compile P
> first.

This is exactly the problem that can occur! (For example, if P,Q were
originally one file that are now split up.)

> When the compiler is compiling P and sees an import referring to Q it
> could:
>
> 1. Check for a file Q.ax which is newer than Q.a. If there is not, scan
> Q.a for exports and build an up-to-date Q.ax without going through a full
> compile of Q.a.
> 2. Use Q.ax to compile P.a including preparing P.ax.

Suppose that neither P.ax and Q.ax yet exist.

So when compiling P, it can't do: import Q, so a bunch of definitions are
missing.

Maybe, it can do a partial compile of P to extract the global names, but it
is possible that some of those names depend critically on something exported
from Q (a type for example, or some constant value).

That might not happen; maybe it is just a few global functions from each
that need to be collated. But in general, I'm not sure that can be done.

To solve this, if you want to use the import system:

 * Move some critical names in both P and Q into a module common to both
(imported by both; modules can contain just data or just declarations).

* If there are only a few imports causing trouble, declare them in the
traditional manner (as a header file for example)

* Or restructure things so that P and Q are not interdependent.

This why there are some flaws with this. There was another problem I didn't
mention: on one project, instead of just having a single project header file
at the top of each module, each module now has a different list of import
statements! (These are the first few lines of the main module of my last
interpreter:

import clib
import qclib
import pcc_decls
import pcc_tables
import pcc_support
import pcc_win
import pcc_loadbc
import pcc_loadpc
import pcc_memory

And this is what the not-quite-C version was:

#include "pcc_hdr.h"
)

Once it's sorted out, however, creating a new global is a joy: just remember
to add 'global' in front, recompile that module, now it is instantly
available to all others (that import that module).

Also, once structured properly, it is far easier to take, say, pcc_memory
above, and use it in another project; that other project just has:

 import pcc_memory

which will pull in whatever modules /it/ needs.

-- 
bartc 

[toc] | [prev] | [next] | [standalone]


#2206

From"BartC" <bc@freeuk.com>
Date2014-05-06 09:45 +0100
Message-ID<Ni1av.330914$n%4.305139@fx10.am4>
In reply to#2192
"James Harris" <james.harris.1@gmail.com> wrote in message
news:lk8u1q$abe$1@dont-email.me...
> "BartC" <bc@freeuk.com> wrote in message

> Do you have a different way to support separate compilation of modules
> that interface with each other?

Actually there was another way I used to do this. Still based on include
files, and still requiring some names to declared both in their 'home'
module and in a header (although this can be partly automated, see below),
but still one level of sophistication above C's system:

* Generally, such include files were /not/ specified in the modules
themselves.

* When compiling a module, the compiler was also provided with the name of
just one header file

* This header file might just consist of a list of includes (normally
constructed by an IDE from from files it knows are headers)

* This header file is compiled as a separate, outer scope to the main
module. (So it was possible to have a name ABC in the header, and override
that with a local file-scope name ABC in the module.) There was no namespace
system however.

* In the header file (or any of its include files), data could be declared,
both initialised (tables etc) and not initialised. This data belonged to the
header, not to any module.

* For the above reason, the header itself forms a separate module that is
also compiled (sans header in this case) and linked.

* Names in the header don't need global or external attributes; the compiler
will know what to apply.

So no headers or imports are necessary at all in any module. (Normal include
files could be used, but the contents are just treated as though they are
part of the module source, using the same scope. Traditional external
declarations could be used in the module too.)

That language still required 'prototypes' for its functions: local ones for
local functions, and global ones in the main header. (Shared variables, type
defs, and constants were simply declared once in the header.)

With another project that was a thin wrapper around C, the translator (a
simple 400-line program) also collated the functions, into local ones and
global ones (which had a 'global' prefix), and generated two extra files: a
.cl file containing the local prototypes, and a .cx file containing the
global/exported ones.

The .cl file was simply included in its own module. The .cx file was
included in the project header. Any changes to a module's .cx file also
sometimes required a 'compile-all'.

Anyway, I don't think it's hard to come up with something 'better' that C's
system of headers (which are just includes files after all, not really 
headers with any special significance).

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#2183

From"Rod Pemberton" <dont_use_email@xnothavet.cqm>
Date2014-05-05 07:33 -0400
Message-ID<op.xfdw11vx6zenlw@localhost>
In reply to#2178
On Mon, 05 May 2014 03:47:01 -0400, James Harris  
<james.harris.1@gmail.com> wrote:

> In two recent threads we discussed good and bad points about C. Some good
> things were mentioned but the focus was mainly on the points that we  
> would
> like to fix. I got to wondering if there could be considered a "good"  
> subset
> of C - i.e. of the whole programming approach including language,  
> preprocessor,
> standard library etc.
>
> The subset should be much easier to compile than full C but it does not
> need to do everything that a programming language should; things could be
> added.
>
> Put another way, if you were designing a new language based on C what
> parts of C would you keep in?
>

It's really a question of how minimal or how primitive do you want that
subset to be.  It's useful either way, just a question of how useful.

I'd say you need an if statement, one loop statement - while(1), break,
switch, curly braces, most of C's math and assignment operators, pointers,
functions, ability to take addresses of object &, ability to dereference
pointers to data and to call functions *, subscript operator for
"arrays" [], structs, typedefs, variables, unsigned char, unsigned long.

A few preprocessor directives such as: #include, #if, #endif, #ifdef,
#define, would be useful.

I'd keep hexadecimal and decimal for number representation.
There is little need for octal for numeric representations.
There is no need for floats.

There is no, or not much, need for goto, continue, unions, or an else
statement.  There is no need for more than two integer types.  One is
for characters and the other for integers.    There is minimal need of
the standard libaries, except <stdio.h>.  You may want a few functions
 from other library include files such as malloc(), free(), exit(),
atexit().  While you need "addressof" &, you generally don't
need "sizeof" sizeof(), or the "typeof" and "alignof" operations
internal to most C compilers.  You can definately forget about any
GNU C extension.

You can eliminate unary operators, pre-dec/increment, most use of the
comma operator, the conditional ?: operator, etc.  Some of C's operators
are redundant or can be expressed using the others, which eliminates
the need for them, especially the numerous assignment operators.
E.g., 'a+=3' becomes 'a=a+3', 'a->b' becomes '(*a).b', and
'a[b]' becomes '*((a)+(b))'.  (So, that's like a lot of them gone ...)
Of course, parenthesis just clutter up the code, so, fix that.  ;-)

For a truly minimalist situation, you can get by without switch, structs,
typedefs, malloc, free, exit, atexit.  However, the language becomes
really annoying without them.  Everything must be declared to be
allocated, and *everything* is pointer based, i.e., to emulate structs
or arrays.  Not having a switch means many if statements, etc.

You could consider eliminating character escape sequences, e.g.,
'\n' '\"' etc.  That will simply strings.  However, you'll have to
use 'putc(0x13)' to do '\n' etc.  Eliminating an escaped quote will
eliminate some parsing issues ...  "quote\"escaped"

You could consider eliminating 'void' and 'void *'.  I.e., go back to
using character pointers.


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#2184

From"BartC" <bc@freeuk.com>
Date2014-05-05 19:14 +0100
Message-ID<4yQ9v.196602$t%4.25057@fx04.am4>
In reply to#2183
"Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message
news:op.xfdw11vx6zenlw@localhost...
> On Mon, 05 May 2014 03:47:01 -0400, James Harris

> There is no, or not much, need for goto, continue, unions, or an else
> statement.

Without 'else' or 'goto', then programming is not going to be much fun.

Here's an example of unstructured C that doesn't use any control flow
statements except if and goto, which are always used together:

http://pastebin.com/dmceAVhM

Without 'goto', then generating 'flat' code like this would be a lot harder.

(In terms of complexity, those two add very little to an implementation. In 
fact a lot of syntax isn't difficult to add so it doesn't make sense to get 
rid of it)

-- 
Bartc 

[toc] | [prev] | [next] | [standalone]


#2187

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-05 20:12 +0100
Message-ID<lk8nrc$ov4$1@dont-email.me>
In reply to#2183
"Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message 
news:op.xfdw11vx6zenlw@localhost...

...

>> Put another way, if you were designing a new language based on C what
>> parts of C would you keep in?
>>
>
> It's really a question of how minimal or how primitive do you want that
> subset to be.  It's useful either way, just a question of how useful.
>
> I'd say you need an if statement, one loop statement - while(1), break,
> switch, curly braces, most of C's math and assignment operators, pointers,
> functions, ability to take addresses of object &, ability to dereference
> pointers to data and to call functions *, subscript operator for
> "arrays" [], structs, typedefs, variables, unsigned char, unsigned long.
>
> A few preprocessor directives such as: #include, #if, #endif, #ifdef,
> #define, would be useful.

You are probably right but it would be good to drop the preprocessor, if 
possible, because it is significant to write and a bit of an anomaly. It is 
like a separate language mixed in with C. But I cannot think how to bring in 
the definitions of structs (from which field offsets are calculated) without 
header files. Umm... maybe all structs could be required to be local to the 
source file which uses them. I'll have to give that some more thought. 
Enumerated constants could be brought in by other mechanisms such as 
importing them.

Could useful #defines be replaced by constants and/or having multiple 
passes?

Could #if and friends be omitted, for example by including executable tests 
in the code?

... (snipped your other comments - agreed with)

James

[toc] | [prev] | [next] | [standalone]


#2197

From"Rod Pemberton" <dont_use_email@xnothavet.cqm>
Date2014-05-05 18:57 -0400
Message-ID<op.xfesqctt6zenlw@localhost>
In reply to#2187
On Mon, 05 May 2014 15:12:47 -0400, James Harris  
<james.harris.1@gmail.com> wrote:
> "Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message  
> news:op.xfdw11vx6zenlw@localhost...

> But I cannot think how to bring in the definitions of structs
> (from which field offsets are calculated) without header files.

Well, I mentioned these:
address of - address operator & - part of C
sizeof() operator - part of C
typeof - part of the compilers
alignof - part of the compiler

But, I forgot this one:
offsetof() - part of C (macro in stddef.h)

offsetof() gets the offsets of something, like the element of a struct
or union.  Look at the macro in stddef.h or Google "offsetof macro".

Usually, they cast 0 or NULL as a pointer to a char or void as the
starting address of the appropriate type (struct or union), then
they subtract that from the address of a component, using the same
cast for the starting address, -> for component selection, & address
operator for the component's address, and a cast of the address to
a pointer to a char or void.

If you have a preprocessor, you can use it.  If not, I think you'll
have to insert an expanded definition everywhere you need it ...,
or perhaps implement it within the compiler.  The compiler should
have the necessary information to do it since it knows the struct
or union layout and sizes of everything in it's symbol tables etc.

> Could #if and friends be omitted, for example by including
> executable tests in the code?

#if #endif #ifdef could be replaced by regular if statements,
with a flag or variable to indicate which code is active.

#define's in the code can be replaced with the value or expanded
macro, etc.

I don't think there is an easy way to handle #include, except
cut-n-paste the entire include ...


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#2209

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-07 11:55 +0100
Message-ID<lkd3fo$2mv$1@dont-email.me>
In reply to#2197
"Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message 
news:op.xfesqctt6zenlw@localhost...
> On Mon, 05 May 2014 15:12:47 -0400, James Harris 
> <james.harris.1@gmail.com> wrote:
>> "Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message 
>> news:op.xfdw11vx6zenlw@localhost...
>
>> But I cannot think how to bring in the definitions of structs
>> (from which field offsets are calculated) without header files.
>
> Well, I mentioned these:
> address of - address operator & - part of C
> sizeof() operator - part of C
> typeof - part of the compilers
> alignof - part of the compiler
>
> But, I forgot this one:
> offsetof() - part of C (macro in stddef.h)
>
> offsetof() gets the offsets of something, like the element of a struct
> or union.  Look at the macro in stddef.h or Google "offsetof macro".

Thanks, I didn't know about offsetof.

...

> If you have a preprocessor, you can use it.  If not, I think you'll
> have to insert an expanded definition everywhere you need it ...,
> or perhaps implement it within the compiler.  The compiler should
> have the necessary information to do it since it knows the struct
> or union layout and sizes of everything in it's symbol tables etc.

Let's take a step back as I didn't clearly explain the point I was making 
about headers. I was thinking that they normally contain the interface 
information for a source file. For a source file called source.c the header 
will normally be called source.h and it will define all of the info that 
another source file needs in order to interface with functions in source.c. 
So any program that wants to call services in source.c will #include 
source.h first. That will tell the compiler the interface info it needs to 
know.

What might header source.h contain? Here are two possible types of 
information:

1. Integer constants. For example, EOF in stdio.h.
2. Structs. For example, struct timespec in time.h.

Header files are a poor mechanism because there is no guarantee that the 
header used when the caller is compiled is the same header that was used 
when the callee is compiled. But with some discipline they can be effective.

I was trying to say that things like struct timespec would need to be 
communicated to a program that interfaces with time functions. If the caller 
wants to update field tv_nsec of a struct timespec it needs to know its 
offset and its type at compile time. Without the header mechanism how could 
that info be made available to the calling module?

>> Could #if and friends be omitted, for example by including
>> executable tests in the code?
>
> #if #endif #ifdef could be replaced by regular if statements,
> with a flag or variable to indicate which code is active.

Good.

> #define's in the code can be replaced with the value or expanded
> macro, etc.

What about the EOF example, above? How would a caller which needed to know 
the value of EOF used by the standard IO functions know what value EOF had 
been set to?

> I don't think there is an easy way to handle #include, except
> cut-n-paste the entire include ...

Not sure. Maybe the individual parts which are #included could be 
communicated in some other - better - way.

James

[toc] | [prev] | [next] | [standalone]


#2217

From"Rod Pemberton" <dont_use_email@xnothavet.cqm>
Date2014-05-07 19:04 -0400
Message-ID<op.xfiic4pj6zenlw@localhost>
In reply to#2209
On Wed, 07 May 2014 06:55:57 -0400, James Harris  
<james.harris.1@gmail.com> wrote:
> "Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message
> news:op.xfesqctt6zenlw@localhost...

>> If you have a preprocessor, you can use it.  If not, I think you'll
>> have to insert an expanded definition everywhere you need it ...,
>> or perhaps implement it within the compiler.  The compiler should
>> have the necessary information to do it since it knows the struct
>> or union layout and sizes of everything in it's symbol tables etc.
>
> Let's take a step back as I didn't clearly explain the point I was making
> about headers. I was thinking that they normally contain the interface
> information for a source file. For a source file called source.c the  
> header will normally be called source.h and it will define all of the
> info that another source file needs in order to interface with functions
> in source.c.
>
> So any program that wants to call services in source.c will #include
> source.h first. That will tell the compiler the interface info it needs
> to know.

That's one way to do it.  That's commonly done for C, but not required.
Personally, I prefer all-in-one programs if they're small.

> What might header source.h contain? Here are two possible types of
> information:
>
> 1. Integer constants. For example, EOF in stdio.h.
> 2. Structs. For example, struct timespec in time.h.
>

function prototypes, structs, unions, enums, #defines, macros, ...

> Header files are a poor mechanism because there is no guarantee that the
> header used when the caller is compiled is the same header that was used
> when the callee is compiled. But with some discipline they can be
> effective.

Should a distinction be maded between a program which includes it's own
header file and a program which includes a C library header file?

In one case, the source which uses those headers are compiled too, but
not for the other.  The other is compiled as a library.

> I was trying to say that things like struct timespec would need to be
> communicated to a program that interfaces with time functions.

So, you're planning to object-orient-ize that struct somehow?  ;-)

> If the caller wants to update field tv_nsec of a struct timespec it
> needs to know its offset and its type at compile time.

Yes.

> Without the header mechanism how could that info be made available
> to the calling module?

Didn't we have some conversation on something like this at least once
before, i.e., in reference to passing structs and data over a network?

It could query what fields the function expects, but I don't quickly
recognize how the code would decide what to put into the fields.

I.e., some intelligence is involved here, which can be captured by the
code, but it's better if each side understands what to expect.  E.g.,
if the calling module expects to pass a struct of a certain format, an
integer, and a string, but the queried function says the struct has
more members, the string is the wrong size, etc how does the callee
fix that?

> What about the EOF example, above? How would a caller which needed
> to know the value of EOF used by the standard IO functions know
> what value EOF had been set to?

That one is more concrete.  If the code was designed to support
different EOF values, then code could query the value the other side
is using and use that.  If the code is compiled for a value
which is different, then the code isn't going to be compatible.

> [better way]

What's with the need for all the abstraction?

Are you still working on object-oriented stuff?


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#2221

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-08 10:14 +0100
Message-ID<lkfht2$k2p$1@dont-email.me>
In reply to#2217
"Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message 
news:op.xfiic4pj6zenlw@localhost...

...

>> What might header source.h contain? Here are two possible types of
>> information:
>>
>> 1. Integer constants. For example, EOF in stdio.h.
>> 2. Structs. For example, struct timespec in time.h.
>>
>
> function prototypes, structs, unions, enums, #defines, macros, ...

Function prototypes are an especially good example.

>> Header files are a poor mechanism because there is no guarantee that the
>> header used when the caller is compiled is the same header that was used
>> when the callee is compiled. But with some discipline they can be
>> effective.
>
> Should a distinction be maded between a program which includes it's own
> header file and a program which includes a C library header file?
>
> In one case, the source which uses those headers are compiled too, but
> not for the other.  The other is compiled as a library.

Sorry, I didn't understand that point.

>> I was trying to say that things like struct timespec would need to be
>> communicated to a program that interfaces with time functions.
>
> So, you're planning to object-orient-ize that struct somehow?  ;-)

I see the smiley so know you are kidding but I cannot see the connection. I 
wasn't thinking of any object orientation issues here. If your comment is 
about me saying "communicated to a program that interfaces with" I was 
thinking only about info comminicated at compile time - nothing dynamic.

>> If the caller wants to update field tv_nsec of a struct timespec it
>> needs to know its offset and its type at compile time.
>
> Yes.
>
>> Without the header mechanism how could that info be made available
>> to the calling module?
>
> Didn't we have some conversation on something like this at least once
> before, i.e., in reference to passing structs and data over a network?

If we did that sounds like a dynamic issue. The info in the header such as a 
struct layout is about compile time so is very static! As an example of a 
header communicating a structure layout consider compiling the following 
reference to a structure

  struct timespec *tp;
  tp->tv_nsec = 0;

That might compile to

  mov [esi + 4], dword 0

The point is that to produce this code the offset (4 in this case) of the 
field from the pointer needs to be known at compile time. The header would 
supply the struct definition from which the compiler works out the offset.

I suppose the offset (4) might be filled in a link or load time. 
Interesting!

> It could query what fields the function expects, but I don't quickly
> recognize how the code would decide what to put into the fields.
>
> I.e., some intelligence is involved here, which can be captured by the
> code, but it's better if each side understands what to expect.  E.g.,
> if the calling module expects to pass a struct of a certain format, an
> integer, and a string, but the queried function says the struct has
> more members, the string is the wrong size, etc how does the callee
> fix that?

Yes, C's header mechanism normally supplies the interface info so that they 
match... as long as the right header is used, that is!

>> What about the EOF example, above? How would a caller which needed
>> to know the value of EOF used by the standard IO functions know
>> what value EOF had been set to?
>
> That one is more concrete.  If the code was designed to support
> different EOF values, then code could query the value the other side
> is using and use that.  If the code is compiled for a value
> which is different, then the code isn't going to be compatible.

I think this too is normally done at compile time so that, for example,

  if (retval == EOF)

might compile to

  cmp eax, -1

where, in this case, I have used -1 for EOF. The specific value would have 
come from a header, probably stdio.h.

> What's with the need for all the abstraction?

Hard to answer that as I'm not sure that there is a lot of abstraction here 
(in the C header mechanism, that is).

> Are you still working on object-oriented stuff?

Umm, not in connection with this but, depending on what you mean, possibly. 
Might make an interesting topic for a separate thread...?

James

[toc] | [prev] | [next] | [standalone]


#2224

From"Rod Pemberton" <dont_use_email@xnothavet.cqm>
Date2014-05-08 07:35 -0400
Message-ID<op.xfjg4u1y6zenlw@localhost>
In reply to#2221
On Thu, 08 May 2014 05:14:10 -0400, James Harris  
<james.harris.1@gmail.com> wrote:
> "Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message
> news:op.xfiic4pj6zenlw@localhost...
>> James wrote:

[added some context back in]

>>> Let's take a step back as I didn't clearly explain the point I was
>>> making about headers. I was thinking that they normally contain the
>>> interface information for a source file. For a source file called
>>> source.c the header will normally be called source.h and it will
>>> define all of the info that another source file needs in order to
>>> interface with functions in source.c.  So any program that wants
>>> to call services in source.c will #include source.h first. That
>>> will tell the compiler the interface info it needs to know.
>>>
>>> [...]
>>>
>>> Header files are a poor mechanism because there is no guarantee that  
>>> the header used when the caller is compiled is the same header that
>>> was used when the callee is compiled. But with some discipline they
>>> can be effective.
>>
>> Should a distinction be maded between a program which includes it's
>> own header file and a program which includes a C library header file?
>>
>> In one case, the source which uses those headers are compiled too,
>> but not for the other.  The other is compiled as a library.
>
> Sorry, I didn't understand that point.
>

A header can be used with both the caller and callee to define the
interface and provide the interface information, yes?  The interface
was defined by/for the callee.  The code which implements the interfaces
is only within the callee.  The header is available to both, so that both
may call that code.  But, there are other situations where headers are
used.  One is where a program uses it's own header, but nothing else does.
If a program defines an interface, that interface isn't shared.  So, the
header is really exclusive to that code.  Should a distinction be made
as to how header files are used?

>>> I was trying to say that things like struct timespec would need to
>>> be communicated to a program that interfaces with time functions.
>>
>> So, you're planning to object-orient-ize that struct somehow?  ;-)
>
> I see the smiley so know you are kidding but I cannot see the
> connection. I wasn't thinking of any object orientation issues here.

Ok.  That's what I was "asking".  I presumed this could be for an
object-oriented situation, or possibly similar in nature.  I was being
humorous in my response but, I perceived converting such a struct to an
object-oriented use might be a bit more complicated.

>>> Without the header mechanism how could that info be made available
>>> to the calling module?
>>
>> Didn't we have some conversation on something like this at least once
>> before, i.e., in reference to passing structs and data over a network?
>
> If we did that sounds like a dynamic issue. The info in the header such  
> as a
> struct layout is about compile time so is very static!

Yes, but it goes to the same or similar nature of the code on one side
not "knowing" what the code on the other side provides and not "knowing"
how to call the interace and not "knowing" what parameters are required.

I.e., I keep getting the impression you're attempting to interface with
a "black box".

> As an example of a header communicating a structure layout consider
> compiling the following reference to a structure
>
>   struct timespec *tp;
>   tp->tv_nsec = 0;
>
> That might compile to
>
>   mov [esi + 4], dword 0
>
> The point is that to produce this code the offset (4 in this case)
> of the field from the pointer needs to be known at compile time.
> The header would supply the struct definition from which the compiler
> works out the offset.
>
> I suppose the offset (4) might be filled in a link or load time.
> Interesting!
>

At some point, you need the offset of tv_nsec and the address of
the timespec struct, or you need the direct address of tv_nsec.
With indirect addressing, you could do something like:

; address timespec + offset tv_nsec

   mov esi, [address_of_tv_nsec_address]
   mov eax, [address_of_tv_nsec_offset]
   lea eax, [esi + eax]
   mov [eax], dword 0

Or,
; address timespec + offset tv_nsec

   mov esi, [address_of_tv_nsec_address]
   mov eax, [address_of_tv_nsec_offset]
   mov [esi + eax], dword 0

Or,
; address tv_nsec
   mov eax, [address_of_tv_nsec]
   mov [eax], dword 0

Here, 'address_of...' are fixed locations in a list or table of all
the other needed addresses and offsets.  The table/list of needed
addresses or offsets are filled in either at compile time or run-time.


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#2226

From"James Harris" <james.harris.1@gmail.com>
Date2014-05-08 16:22 +0100
Message-ID<lkg7fg$aek$1@dont-email.me>
In reply to#2224
"Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message 
news:op.xfjg4u1y6zenlw@localhost...
> On Thu, 08 May 2014 05:14:10 -0400, James Harris 
> <james.harris.1@gmail.com> wrote:
>> "Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message
>> news:op.xfiic4pj6zenlw@localhost...
>>> James wrote:
>
> [added some context back in]
>
>>>> Let's take a step back as I didn't clearly explain the point I was
>>>> making about headers. I was thinking that they normally contain the
>>>> interface information for a source file. For a source file called
>>>> source.c the header will normally be called source.h and it will
>>>> define all of the info that another source file needs in order to
>>>> interface with functions in source.c.  So any program that wants
>>>> to call services in source.c will #include source.h first. That
>>>> will tell the compiler the interface info it needs to know.
>>>>
>>>> [...]
>>>>
>>>> Header files are a poor mechanism because there is no guarantee that 
>>>> the header used when the caller is compiled is the same header that
>>>> was used when the callee is compiled. But with some discipline they
>>>> can be effective.
>>>
>>> Should a distinction be maded between a program which includes it's
>>> own header file and a program which includes a C library header file?
>>>
>>> In one case, the source which uses those headers are compiled too,
>>> but not for the other.  The other is compiled as a library.
>>
>> Sorry, I didn't understand that point.
>>
>
> A header can be used with both the caller and callee to define the
> interface and provide the interface information, yes?  The interface
> was defined by/for the callee.  The code which implements the interfaces
> is only within the callee.  The header is available to both, so that both
> may call that code.  But, there are other situations where headers are
> used.  One is where a program uses it's own header, but nothing else does.
> If a program defines an interface, that interface isn't shared.  So, the
> header is really exclusive to that code.  Should a distinction be made
> as to how header files are used?

I can say how I use them. To set a context I should say that #include can 
bring in any source code but is usually used to bring in header files and 
that the content of an included header file could, instead, appear in the 
source instead of the #include statement. So,... what I tend to do is where 
I want something to be private to a source file I write it in the source 
file, and where I want something to be available to other modules I put it 
in a header.

To make an example, say a single source file, source.c, has two functions, 
funcPublic and funcPrivate and that they appear in that order in the source 
file and that funcPublic calls funcPrivate. The files would look as follows.

source.h
  int funcPublic(int); /* Declare the public function */

source.c
  #include "source.h"
  int funcPrivate(int); /* Declare the private function */

Doing it this way means that source.c sees both declarations but another 
module which includes source.h will only see the funcPublic declaration.

Both of the functions would appear later in source.c but because only 
funcPublic appears in a header file it is the only function that other 
source code modules can learn about. Yet within source.c funcPublic and 
funcPrivate will be able to call each other as required.

...

>>>> Without the header mechanism how could that info be made available
>>>> to the calling module?
>>>
>>> Didn't we have some conversation on something like this at least once
>>> before, i.e., in reference to passing structs and data over a network?
>>
>> If we did that sounds like a dynamic issue. The info in the header such 
>> as a
>> struct layout is about compile time so is very static!
>
> Yes, but it goes to the same or similar nature of the code on one side
> not "knowing" what the code on the other side provides and not "knowing"
> how to call the interace and not "knowing" what parameters are required.
>
> I.e., I keep getting the impression you're attempting to interface with
> a "black box".

OK. Am guessing as to why you might get that impression but possibly it is 
because I try to modularise quite a lot. I remember a comment you made 
earlier about keeping things in one module if they are small enough. I do 
that too sometimes but more often try to split things up for a number of 
reasons, e.g. I find it makes them easier to reuse in other projects.

Have you come across these principles?

  http://web.engr.oregonstate.edu/~budd/Books/oopintro3e/info/slides/chap03/slide28.htm

The approach is a form of data hiding and an excellent approach, IMO.

The effort to reduce 'public' information may be why to you I seem to be 
interfacing with a black box. As part of the topic we are discussing, 
though, I would put public interface information into a C header file.

>> As an example of a header communicating a structure layout consider
>> compiling the following reference to a structure
>>
>>   struct timespec *tp;
>>   tp->tv_nsec = 0;
>>
>> That might compile to
>>
>>   mov [esi + 4], dword 0
>>
>> The point is that to produce this code the offset (4 in this case)
>> of the field from the pointer needs to be known at compile time.
>> The header would supply the struct definition from which the compiler
>> works out the offset.
>>
>> I suppose the offset (4) might be filled in a link or load time.
>> Interesting!
>>
>
> At some point, you need the offset of tv_nsec and the address of
> the timespec struct, or you need the direct address of tv_nsec.
> With indirect addressing, you could do something like:
>
> ; address timespec + offset tv_nsec
>
>   mov esi, [address_of_tv_nsec_address]
>   mov eax, [address_of_tv_nsec_offset]
>   lea eax, [esi + eax]
>   mov [eax], dword 0
>
> Or,
> ; address timespec + offset tv_nsec
>
>   mov esi, [address_of_tv_nsec_address]
>   mov eax, [address_of_tv_nsec_offset]
>   mov [esi + eax], dword 0
>
> Or,
> ; address tv_nsec
>   mov eax, [address_of_tv_nsec]
>   mov [eax], dword 0
>
> Here, 'address_of...' are fixed locations in a list or table of all
> the other needed addresses and offsets.  The table/list of needed
> addresses or offsets are filled in either at compile time or run-time.

Yes, I can see the principle. That should work.

James

[toc] | [prev] | [next] | [standalone]


#2229

From"Rod Pemberton" <dont_use_email@xnothavet.cqm>
Date2014-05-09 16:45 -0400
Message-ID<op.xfl1afv66zenlw@localhost>
In reply to#2226
On Thu, 08 May 2014 11:22:31 -0400, James Harris  
<james.harris.1@gmail.com> wrote:
> "Rod Pemberton" <dont_use_email@xnothavet.cqm> wrote in message
> news:op.xfjg4u1y6zenlw@localhost...

>> I.e., I keep getting the impression you're attempting to interface with
>> a "black box".
>
> OK. Am guessing as to why you might get that impression but possibly it
> is because I try to modularise quite a lot.

Ok.  Yeah, that could be it.

It just seems to me sometimes that it's like you're creating something
which has no information about what it is connecting with, none, zero.

;-)

> Have you come across these principles?
>
>   [Parnas "rules"]
>

I'm going to say: "No."

Of course, one could say the phrase "should provide no other information"
of each clause is rather vague, unclear, and/or arbitrary, etc.

What exactly is the meaning of "no other information" in that context?
Does the "no other information" refer to,

A) for the 1st clause:
  1) exclusively information completely unrelated to the "services
provided" or external to it?
  2) #1 and the information for services not necessarily needed for
"effective use" but still provided for use?
  3) any information related to the "services provided" which are
internal to those services which may be exposed to the user?

etc.

B) for the 2nd clause:
  1) information completely unrelated to the "responsibilities
assigned"?
  2) information for responsibilities not assigned but may
eventually be assigned?

etc.

I would have argue that limiting some information, which Parnas
thinks clearly thinks is irrelevant or extraneous, would cause
design or implementation problems in the future.  The phrases
"too limiting" and "too unknown" comes to mind.

E.g., I would expect to have *all* information needed to use
the services even if some of that information is *not* needed
for "effective use".  It may still be required for uses which
are arbitrarily deemed ineffective use by others.

E.g., if your manager says that there is the possibility the
code will be extended in a certain way in the future, you're
going to allow for that in your current design even though
it's *not* an assigned responsibility.  If you don't, you
could have serious problems fixing things in the future.

Rules always have a reason for their existence, but the rules
never tell you _why_ the rule was created in the first place.
The rules never tell you their purpose.  So, you always have
determine why the rule exists, what are the original constraints
under which the rule was created, and then you have to ask if
the rule is still valid or ever made any sense at all.

So, you may want ask yourself what is the real purpose behind
the Parnas rules:

1) is it to prevent code bloat?
2) is it to prevent feature creep?
3) is it to prevent miscommunication?
4) is it to prevent coding mistakes?
5) is it to prevent conflicts between user and developer?
6) is it to control proprietary information?
7) is it to keep a project on target, on budget?
etc.


A "slide" or two back:

"The user of a software component need only know what it does,
not how it does it."

I would agree and disagree with that.  Who is the user?  It doesn't
define who the "user" is.  Without defining that, the statement may
be invalid.  I.e., does user mean *all* users with *no* exceptions?

If the "user" is an end-user of an application, then they can be kept
in the dark.  They only need to understand the application's interface,
and don't need to understand anything to do with the modules involved.
Information hiding works just fine for them.

If the "user" is another computer programmer, then they *absolutely*
need to know what the "software component" does to make a decision as
to whether the component is capable of "effective use" or not.

A programmer needs to understand the modules interface and how the
module works.  If the programmer goes ahead and uses the "black box"
without understanding what it does because he/she has no access to it,
that could create some future complications.  It may be doing too much,
not enough, be too slow, or be doing something it's not supposed to do.

It seems this is about object-oriented languages, and it mentions
"information hiding".  As a programmer, information hiding is a
*bad* thing.  That's when an internal function has been hidden
or not exposed, or when access to it has been denied.  It's always
in those situations that you find you need access to that component.
You know what you need is in there, but you can't use it, e.g.,
intermediate operation in a C library function, or a sub-function
used by the OS, etc.

IMO, one of the reasons that C is viewed as a "rich" language for
programming is because almost everything the language does is available
to the programmer for their use, i.e., very little is hidden or restricted.

> The approach is a form of data hiding and an excellent approach, IMO.
>
> The effort to reduce 'public' information may be why to you I seem to be
> interfacing with a black box. As part of the topic we are discussing,
> though, I would put public interface information into a C header file.

...


Rod Pemberton

[toc] | [prev] | [next] | [standalone]


#2230

From"Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Date2014-05-10 09:04 +0200
Message-ID<1jy1ogca55286$.hxrf634zi430$.dlg@40tude.net>
In reply to#2229
On Fri, 09 May 2014 16:45:41 -0400, Rod Pemberton wrote:

> On Thu, 08 May 2014 11:22:31 -0400, James Harris  
> <james.harris.1@gmail.com> wrote:
>> Have you come across these principles?
>>
>>   [Parnas "rules"]
> 
> I'm going to say: "No."
> 
> Of course, one could say the phrase "should provide no other information"
> of each clause is rather vague, unclear, and/or arbitrary, etc.
> 
> What exactly is the meaning of "no other information" in that context?
> Does the "no other information" refer to,

You missed another important software design principle: a program must be
designed in a way that separates information needed for use (interface) and
arbitrary, thus volatile information (implementation).

If you disregard this, then Parnas' principles make no sense.

> It seems this is about object-oriented languages, and it mentions
> "information hiding".  As a programmer, information hiding is a
> *bad* thing.

No, it is a method of maintaining complexity and so of making collective
software production possible (roles, separate design, testing,
maintenance).

It is not bad or good, it is the only way software engineering may
function. Yes, proper engineering processes and techniques on small scale
are considered unnecessary overhead, boring, and they certainly are. The
problem is that programmes can only be taught on small things first. This
is why C is so popular, and also so damaging to software developing in
general. 

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

[toc] | [prev] | [next] | [standalone]


Page 1 of 4  [1] 2 3 4  Next page →

Back to top | Article view | comp.lang.misc


csiph-web