Searching \ for '[TECH] language - was [PIC] using BREAK in 'C'' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page: www.piclist.com/techref/microchip/languages.htm?key=language
Search entire site for: 'language - was [PIC] using BREAK in 'C''.

Exact match. Not showing close matches.
PICList Thread
'[TECH] language - was [PIC] using BREAK in 'C''
2009\07\06@160035 by sergio masci

flavicon
face


On Mon, 6 Jul 2009, Gerhard Fiedler wrote:

> sergio masci wrote:
> >

> Yes. You can send this to your marketing department -- I never can
> remember which way it is :)

Ok I'll be sure to pass this on to the left side of my desk :-)

{Quote hidden}

You are explicitly seeing sin() where I have tried highlighting the brick
wall between the compiler and the knowledge excapsulated in a library
function.

I chose sin because to a great many people it is a black box which they
can relate to rather than some complex function that I'd invent as an
example.

Yes the compiler writer could allow the programmer to attach a ton of
attributes to a library function to help it understand the function better
but that's not the point. The point is to make it simpler for a programmer
to write good code that is easy to maintain - to allow the compiler to
extract the necessary information from the function itself without the
programmer needing to add extra attributes - which like comments might
actually be at odds with the code and be wrong (yet something else to
debug).

Yes the compiler could try to evaluate the 'blackbox' function at compile
time in order to generate a compile time constant but this is not the
point. It is a way of getting the same result as would be obtained as a
side effect "of the point".

Let's try something a little bit more interesting:

void delete_item(int pos, int *len, int arr[])
{
       int        j;

       for (j=pos; j<*len; j++)
       {
               arr[j] = arr[j+1];
       }

       *len--;
}

void insert_item(int pos, int val, int *len, int arr[])
{
       int        j;

       for (j=*len-1; j>pos; j--)
       {
               arr[j] = arr[j-1];
       }

       *len++;

       arr[pos] = val;
}

main()
{
...
       delete_item(pos, &len, arr);
       insert_item(pos, val, &len, arr);
...
}


Now how would you give the compiler enough information in the attributes
of the functions to be able to automatically optimise the above into the
equivalent of:

       replace_item(pos, &len, arr);

I can see how you would do this easily if the compiler actually new the
intent of delete_item and insert_item.

A far more concrete example would be that of having multitasking built
into the language rather than as a bolt-on library. XCSB knows about
multitasking and generates optimised code around it. You don't need to
generate several stacks and functions that need to be re-enterent just in
case they are being used in several tasks. Don't you think that's a
benefit? I mean the fact that you can get tight efficient multitasking
code written in a HLL to work on something as small as a 16F628?

{Quote hidden}

This was a trivial example but consider a much more real case where the
above code would actually exist in a library as part of the 'init'
sequence of a module. Ideally the programmer would be insulated from
having to build large complex static tables within his/her main line. This
should all be taken care of by the library writer / maintainer.

You must have come across some horrible libraries yourself where several
things need to be declared as "#defines" before the corresponding header
of the library is included into your main line for the sake of efficiency.

{Quote hidden}

The standard template library is still a brick wall to the compiler. It
can do a lot of optimisations in situ which give the illusion that the
compiler understands what the intent is but the reallity is that the
compiler is just blindly reducing intermediate code as much as it can
(kind of like macros on steroids) and then using what's left to generate
the executable. It's not looking for special patterns of use and
optimising at a high level which is what YOU are doing when you create
your special optimised containers.

Another way to look at this, say you write:

       unsigned char x, j;

       x = j * 2;

The compiler can actually replace "* 2" by "<< 1" because it looks for the
special combination "* 2" operating on an integer. Also the compiler could
optimise "x = j << 1" for the PIC into

       rlf j,w
       movwf x

because it sees the combination of '=' and '<< 1'

If you replaced the operators '=' and '*' with 'assign' and 'mult' such
that the above was re-written as

       assign(&x, mult(j, 2));

how would you give the compiler enough information on the above
functions to be able to do the same level of optimisation as before?

And forgetting about optimisation completely, what about promoting
integers to floats?

e.g.
       float        x;
       int        y, z;

       x = y / z;

here a decent language / compiler could see that the result result needs
to be a float and promot y and z to floats and perform a floating point
division. How would you do that with library functions (even allowing for
overloading)?

How would the compiler do the promotion here?

       assign(&x, div(y, z));


Friendly Regards
Sergio Masci

2009\07\06@162313 by M.L.

flavicon
face

On Mon, Jul 6, 2009 at 7:07 PM, sergio masci<spam_OUTsmplxTakeThisOuTspamallotrope.net> wrote:
> And forgetting about optimisation completely, what about promoting
> integers to floats?
>
> e.g.
>        float   x;
>        int     y, z;
>
>        x = y / z;
>
> here a decent language / compiler could see that the result result needs
> to be a float and promot y and z to floats and perform a floating point
> division.


IIRC the C type is undefined - in any case and you should typecast it to float.
x = (float)(y/z);

I realize this wasn't your point, but it's worth mentioning.
--
Martin K.

2009\07\06@204126 by Gerhard Fiedler

picon face
M.L. wrote:

>> On Mon, Jul 6, 2009 at 7:07 PM, sergio masci<.....smplxKILLspamspam@spam@allotrope.net>
>> wrote:
>> And forgetting about optimisation completely, what about promoting
>> integers to floats?
>>
>> e.g.
>>        float   x;
>>        int     y, z;
>>
>>        x = y / z;
>>
>> here a decent language / compiler could see that the result result
>> needs to be a float and promot y and z to floats and perform a
>> floating point division.
>
> IIRC the C type is undefined ...

Not sure what you mean by "undefined"; the expression "y / z" in the
code above has a result type of int (both values are of type int).

> ... - in any case and you should typecast it to float.
>
> x = (float)(y/z);

This isn't changing anything. This cast is implicit already in Sergio's
code. The division is still executed as integer division, then the
result is cast to float. This is exactly what the first code above does.

I suspect you mean something like

 x = (float)y / z;

which explicitly casts y to float, then by the promotion rules
implicitly casts y and z to double and executes the division as double
division, then casts the result down to float. (IIRC... I don't do a lot
of implicit casting of floats; I actually almost never use float.)

Gerhard

2009\07\06@205149 by M.L.

flavicon
face

On Mon, Jul 6, 2009 at 8:41 PM, Gerhard
Fiedler<listsspamKILLspamconnectionbrazil.com> wrote:
>> ... - in any case and you should typecast it to float.
>>
>> x = (float)(y/z);
>
> This isn't changing anything. This cast is implicit already in Sergio's
> code. The division is still executed as integer division, then the
> result is cast to float. This is exactly what the first code above does.
>
> I suspect you mean something like
>
>  x = (float)y / z;

Yes, I did. I thought of that after the fact.

-
Martin

2009\07\08@093620 by Gerhard Fiedler

picon face
sergio masci wrote:

> I chose sin because to a great many people it is a black box which
> they can relate to rather than some complex function that I'd invent
> as an example.
>
> Yes the compiler writer could allow the programmer to attach a ton of
> attributes to a library function to help it understand the function
> better but that's not the point. The point is to make it simpler for
> a programmer to write good code that is easy to maintain - to allow
> the compiler to extract the necessary information from the function
> itself without the programmer needing to add extra attributes - which
> like comments might actually be at odds with the code and be wrong
> (yet something else to debug).

I was talking about standard libraries, where the programmer doesn't
have to attach anything. The difference between libraries in general and
standard libraries is that the standard libraries must conform to a
standard to be a standard library, not any more or any less than a
compiler. Of course such a standard in general doesn't define how it is
implemented, but it defines what it does.

{Quote hidden}

This function should have been part of the interface in the first place.
This is the tricky part of defining a good library interface: provide
the interface that makes sense.

> A far more concrete example would be that of having multitasking built
> into the language rather than as a bolt-on library. XCSB knows about
> multitasking and generates optimised code around it. You don't need
> to generate several stacks and functions that need to be re-enterent
> just in case they are being used in several tasks. Don't you think
> that's a benefit?

Of course. C for example lacks any multitasking specification; it wasn't
relevant at the time the C spec was created, because it was handled by
the operating system, exclusively. Now it's common for applications to
do multithreading inside the application, and this shows the
shortcomings of a suitable standardization.

But besides this, I think that what you are talking about is an
optimization. The compiler should have enough knowledge to be able to do
it, and it should be specified well enough so that multitasking features
are specified, but I still fail to see the big difference whether this
is specified as a standard library or as part of the compiler.

> I mean the fact that you can get tight efficient multitasking code
> written in a HLL to work on something as small as a 16F628?

People do it all the time. It is of course a feat to have this built
into the compiler. The real feat is, however, to design this and
standardize this in a way that it is efficient and suitable for
everything from an embedded application running on "bare metal" in a
16F628 to an embedded application running on a stripped down Linux in an
ARM to a desktop application running on Windows XP in a multicore
processor.


{Quote hidden}

Of course. But this is just a side effect of a limitation of C, not of
the fact that this was in a library rather than in the compiler. Much of
this ugly preprocessor code you're referring to is due to the fact that
the C language doesn't specify much (if any?) compile-time evaluations.
To do this, people have to resort to the preprocessor. Complex
compile-time evaluations could/should part of a good language
definition; it would help a lot, especially on small systems. But IMO
this hasn't much to do with whether these calculations are defined in
library code or in something that's supported by the compiler directly.


> If you replaced the operators '=' and '*' with 'assign' and 'mult' such
> that the above was re-written as
>
>        assign(&x, mult(j, 2));
>
> how would you give the compiler enough information on the above
> functions to be able to do the same level of optimisation as before?

If the semantics of assign and mult are clearly defined by a standard,
it could do the same optimizations.

{Quote hidden}

This may be what the programmer wants, or not. The compiler doesn't know
whether I want y/z be an integer division or a float division or a
double division. Chances are that if I had written this, it wouldn't be
what I want. But I don't write such code; I tend to use explicit casts
to make sure both the compiler and the human reader of the code know
what the code is supposed to do. If I could, I'd disable automatic
promotions in C and C++, so that I don't forget any explicit cast. Where
compilers have warnings for this, I enable them.

> How would you do that with library functions (even allowing for
> overloading)?

This is just a matter of how you define automatic promotions. But I'm
not a huge fan of automatic promotions; it's just not that easy to get
them right (I mean to get the rules right so that they make sense and
don't create more confusion than they help), and the work involved (for
the programmer) is IMO more with automatic promotions (always need to be
on the lookout for the cases where the automatic promotions don't work
as needed) than with manual type casts.

In the case above, if I wanted to assign the integer division result of
y/z to the float x, I'd have to remember to use a temporary intermediate
variable, so that the compiler actually does what I want:

       float        x;
       int        y, z;

       int        temp; // Only needed to "trick" the compiler
       temp = y / z; // into doing what I want.
       x = temp;

I don't like this anymore than I like the C style automatic promotions.
I'm a declared fan of explicit type casts.


> How would the compiler do the promotion here?
>
>        assign(&x, div(y, z));

Depending on how the language standard defines them, and the way
assign() is declared. I still fail to see what the difference is between
an operator '=' and a function assign(). (In fact, in C++ there isn't
even any, built-in or library.)


Of course, I agree that there probably are some optimizations that can
be done when the code generation is in charge of everything. But it
seems that so far you couldn't bring a good example where the difference
wasn't in something else. The first examples were about compile-time
evaluations, which are not part of the C standard, but could be part of
a similar language standard. The latter examples were about function
calls where the functions are "black boxes" to the compiler, ignoring
the fact that for /standard/ library functions, the compiler knows
exactly what they do (or are supposed to do).

Gerhard

2009\07\08@104403 by olin piclist

face picon face
Gerhard Fiedler wrote:
>  float x;
>  int y, z;
>
> int temp; // Only needed to "trick" the compiler
> temp = y / z; // into doing what I want.
>  x = temp;
>
> I don't like this anymore than I like the C style automatic promotions.

As you said, yucc.  For any of you that might be interested, Pascal solves
this in a nice way by having two divide operators, "/" and "div".  "/"
always produces a floating point result, whether performed on integers or
not.  Div always does a integer divide, can only be performed on integers,
and produces a integer result.  This scheme provides both the necessary
information to the compiler and good readability in the source code.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\08@142031 by sergio masci

flavicon
face


On Wed, 8 Jul 2009, Olin Lathrop wrote:

{Quote hidden}

Likewise FYI: XCSB decides on which division operator to use depending on
where the result is to go. So:

       float        x
       int        y, z

       x = y / z

would use a floating point division because the expected result is a
floating point. If you wanted to use integer division you would write:

       x = (int)(y / z)

This actually tells the compiler that you want to produce an integer as
the result of the division.

Friendly Regards
Sergio Masci

2009\07\08@145133 by sergio masci

flavicon
face


On Wed, 8 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

So you are saying a standard library (I thought you were talking about the
STL as you were also discussing containers at the time) should be
different to a user defined library? I think the users would eat you alive
if you dared create a divide between the standard and user libraries (such
that the user libraries could not optimised to the same high level as the
standard libraries).

{Quote hidden}

No you've missed my point here. It's not that the function was missing
it's that the programmer didn't use it and the compiler had no way of
knowing that there was a better way to do things - because they were
library functions with a brick wall in the way.

{Quote hidden}

I think you might want to check that. C was used in multitasking
situations on bare metal (without a cosey OS or even a supervisor) for
some time before the C spec was created. Look at all the apps written for
embedded or process control systems in C. Also OCCAM and ADA supported
multitasking directly.

> Now it's common for applications to
> do multithreading inside the application, and this shows the
> shortcomings of a suitable standardization.
>
> But besides this, I think that what you are talking about is an
> optimization. The compiler should have enough knowledge to be able to do
> it, and it should be specified well enough so that multitasking features
> are specified, but I still fail to see the big difference whether this
> is specified as a standard library or as part of the compiler.

It's to do with giving the compiler more information on which to base its
analysis of the source code. The more information you give it the better
job it can do. This results in a greater ability to catch errors and
generate robust optimised code.

When you write a small fragment of code and you know (for example) that it
only has to count a maximum of say 10 items, you can decide to use an 8
bit wide unsigned integer to do the counting within that small fragment.
The knowledge you have is not actually present within that small fragment
of code and there is no way that the compiler can verify that any changes
you make later on in some other piece of code do not conflict with this
"10 item assumption" for this fragment UNLESS you jump through hoops to
try to tie this "10 item requirement" to this fragment. You should not
need to jump through hoops to do this and the compiler should be able to
take this requirement and propergate it throughout the rest of the
executable that it is building. The function interfaces in libraries act
as brick walls impeading this process.

{Quote hidden}

I understand that SOME people have had success doing this is assembler for
a small MCU like the 628 but I am not aware of any C / library combination
that is efficient enough to allow you to do any more than flash a few LEDs
on a 628. If you know of any please let me know.

Having a language and compiler that would generate efficient multitasking
code on both a 628 and Windows XP in a multicore processor would be a
feat. But the hardest part (that of getting it to work on a 628) is done!
Surely you can see that doing the same for a system with MUCH better
resources is trivial in comparison. Even if the XCSB compiler were to
generate simple intermediate C source code for the XP system the fact is
that you could have the same XCSB code running on both the 628 and XP (if
we ignore the hardware specific registers).

{Quote hidden}

This discussion certainly is helping me think more deeply about things I
have taken for granted for a long time now.

For one thing I wonder just how popular C would have been without the
conditional compilation capability provided by the C pre-processor.
Allowing one set of source files to be compiled for different targets.
There again the interface between the pre-processor and the compiler
proper is another brick wall.

{Quote hidden}

Yes it could but again it would be down to the compiler to generate the
appropriote optimised code and not just generate code to handle the
calling protocol of library functions.

Can you not see that in adding more and more attributes to the library all
you are really doing is trying to push the libraries into the compiler?

{Quote hidden}

Yes but we are talking about what comes naturaly not what comes of years
of discipline of using a particular language. A great many pleople get
caught with this type of integer division in C. It takes years for many
people to reliably use integer division (without the odd slip). The
compiler is there to help you. The computer is there to do what you want.

You souldn't need to do what does not come naturaly. That's error prone.

{Quote hidden}

In XCSB the compiler says "Ah, you want to assign the result to a floating
point variable therefor I wont just discard the remainder I'll do the calc
as a float". In XCSB if you wanted to do an integer division even though
the result should be a float you would do

       x = (int)(y / z)

{Quote hidden}

There are many aspects to this compiler verses libraries debate. The
biggest problem is the brick wall between the source code the compiler is
trying to analyse and the library. "Compile-time evaluations", "function
calls as 'black boxes'" these are dependent on the "brick wall". This is
what I am trying to describe. You say that I am:

       "ignoring the fact that for /standard/ library functions, the
       compiler knows exactly what they do (or are supposed to do)."

I'm not. The fact is the compiler does not know. It has an interface
definition for each funtion in the form of a function prototype in a
header file somewhere. But that's about it. The compiler is only given
enough info on the function to allow it to comply with the protocol for
invoking the function. You can extend the compiler so that function
prototypes can have special attributes (like GCC) such that you tell the
compiler "hey, this function doesn't use any statics, or global variables,
it only modifies its own locals and its result is totally dependent on the
input value". Ok so you can do that, but what else can you do? Actually
very little. GCC only has a handfull of such attributes that you can use
for a function.

If you're going to implement something that would allow the "standard"
library to be used in the same way as a more intelligent compiler for a
much more sophisticated language than C for C then you are going to have
to do a hell of a lot of work. It's not something you could easily tack
onto C.

Friendly Regards
Sergio Masci

2009\07\09@085658 by Gerhard Fiedler

picon face
sergio masci wrote:

>> I was talking about standard libraries, where the programmer doesn't
>> have to attach anything. The difference between libraries in general
>> and standard libraries is that the standard libraries must conform
>> to a standard to be a standard library, not any more or any less
>> than a compiler. Of course such a standard in general doesn't define
>> how it is implemented, but it defines what it does.
>
> So you are saying a standard library (I thought you were talking
> about the STL as you were also discussing containers at the time)
> should be different to a user defined library? I think the users
> would eat you alive if you dared create a divide between the standard
> and user libraries (such that the user libraries could not optimised
> to the same high level as the standard libraries).

You were talking about intent. For a normal library, the compiler
doesn't know about intent. For a library with a standardized interface
(for example, the C++ STL) the compiler does know about intent.

>> This function should have been part of the interface in the first
>> place. This is the tricky part of defining a good library interface:
>> provide the interface that makes sense.
>
> No you've missed my point here. It's not that the function was
> missing it's that the programmer didn't use it and the compiler had
> no way of knowing that there was a better way to do things - because
> they were library functions with a brick wall in the way.

I'm not sure whether you're not missing my point. If all three functions
are defined as functions of a standard library (including their
semantics), the compiler "knows" about them and what they do. And if
replace is a suitable (and more efficient) substitution for delete
followed by an insert, it may substitute it.


>> Of course. C for example lacks any multitasking specification; it
>> wasn't relevant at the time the C spec was created, because it was
>> handled by the operating system, exclusively.
>
> I think you might want to check that. C was used in multitasking
> situations on bare metal (without a cosey OS or even a supervisor)
> for some time before the C spec was created. Look at all the apps
> written for embedded or process control systems in C. Also OCCAM and
> ADA supported multitasking directly.

I was talking about C, not about other languages. And besides sequence
points and some additional guarantees for volatile variables, you won't
find many help in the C standard for multitasking, especially when
multiple cores are involved.

It has been done, but one needs to know what one does when doing so, and
it's not necessarily portable. For example, the standard doesn't
prohibit RMW problems that occur because the compiler would load two
16bit variables in a 32bit register, work on one, but write both back
(while potentially the other one has been overwritten in memory by
another thread running on another core). There are a number of other
such problems that are not addressed by the standard.


> Having a language and compiler that would generate efficient
> multitasking code on both a 628 and Windows XP in a multicore
> processor would be a feat. But the hardest part (that of getting it
> to work on a 628) is done! Surely you can see that doing the same for
> a system with MUCH better resources is trivial in comparison.

No, I can't see that. Portable, safe and efficient multitasking on a
modern multicore system is in no way trivial. It is IMO more complex
than multitasking on a 628, by a few magnitudes.


> This discussion certainly is helping me think more deeply about things
> I have taken for granted for a long time now.
>
> For one thing I wonder just how popular C would have been without the
> conditional compilation capability provided by the C pre-processor.
> Allowing one set of source files to be compiled for different
> targets. There again the interface between the pre-processor and the
> compiler proper is another brick wall.

I think they serve different purposes, but the C preprocessor has been
used to address some of the C compiler's shortcomings. I don't think the
separation (or "brick wall") between the two is really a problem. I
think C would be a "better C" (especially for small micros) if it had a
compile-time evaluation capability. And Pascal would have been a better
Pascal if it came with a preprocessor.

(The latter is a bit easier to address if you're not using an integrated
IDE like Turbo Pascal, because then you can add a preprocessor step to
your build step. But then again, everybody would use a different
preprocessor and the code wouldn't be portable again :)


>> If the semantics of assign and mult are clearly defined by a standard,
>> it could do the same optimizations.
>
> Yes it could but again it would be down to the compiler to generate the
> appropriote optimised code and not just generate code to handle the
> calling protocol of library functions.

Right. But sometimes the compiler does generate the code for the library
functions (or at least it's under control of the programmer whether it
does or not), so I'm not seeing the difference.

Of course, the traditional C concept of separate translation units is
just the way you're describing. But this doesn't have to be so, and
supposedly e.g. HiTech's OCG or Microsoft's link-time code generation
are attempts to improve on this.

I think it may be (trying to be careful here :) that you're focusing too
much on some arbitrary limitations of C. It's probably unavoidable, but
many of C's limitations are arbitrary (that is, mostly historical) and
not necessary.

> Can you not see that in adding more and more attributes to the library
> all you are really doing is trying to push the libraries into the
> compiler?

I never thought or wrote about adding attributes to the library. I just
wasn't thinking in terms of separate translation units, I was thinking
of /standard/ libraries (that is, libraries with a clearly defined
interface) and I was thinking about libraries that come in source code.


> Yes but we are talking about what comes naturaly not what comes of
> years of discipline of using a particular language. A great many
> pleople get caught with this type of integer division in C. It takes
> years for many people to reliably use integer division (without the
> odd slip). The compiler is there to help you. The computer is there
> to do what you want.

I think when it comes to type conversion, it should always be explicit.
This is especially important on small systems with limited resources. It
is my experience that more often than not, if you don't do it
explicitly, you have to comment it one way or another. I prefer not to
comment it, but to do it explicitly in the code.

> In XCSB the compiler says "Ah, you want to assign the result to a
> floating point variable therefor I wont just discard the remainder
> I'll do the calc as a float". In XCSB if you wanted to do an integer
> division even though the result should be a float you would do
>
> x = (int)(y / z)

IMO, as I just said, I don't like automatic conversions. I don't think
the compiler has a good chance to figure out what I want. Pinning the
operation on the result is just as dangerous as pinning it on the
operands. I may divide one 32bit int by another 32bit int and put the
result into an 8bit int. I don't want the division to be an 8bit int
division. I may divide an 8bit int by another 8bit int and put the
result into a 32bit int, and I don't want the division to be a 32bit int
division. And so on... I think such type conversions should be explicit.


> I'm not. The fact is the compiler does not know. It has an interface
> definition for each funtion in the form of a function prototype in a
> header file somewhere. But that's about it.

I think this may be the one misunderstanding that we have. I'm thinking
of libraries that are available in source code with a standardized and
clearly defined interface, like most (if not all) C++ standard
libraries.

Also, even though the comparison between XSCB (did I get it right this
time? :) and C is kind of underlying here, I don't think that C's
arbitrary limitations are relevant to this discussion /in principle/.

I know that for everyday work, you don't compile the standard library;
you use pre-compiled "brick walled" object code libraries. (I don't know
how much e.g. Microsoft's link-time code generation does bring here;
supposedly, since it's at link time, it would also optimize library code
that's pre-compiled.) But nothing would prevent the programmer from
running the compiler on the whole source code.

Gerhard

2009\07\09@102651 by olin piclist

face picon face
Gerhard Fiedler wrote:
> You were talking about intent. For a normal library, the compiler
> doesn't know about intent. For a library with a standardized interface
> (for example, the C++ STL) the compiler does know about intent.

I think you guys are talking past each other.  I think what Gerhard is
trying to say, but not doing a good job of it, is that he wants things that
look like library calls but that are really intrinsic functions that the
compiler understands natively.  The compiler would completely know the
intent of these functions and would be free to write in line code, call a
runtime library function, or optimize the "call" in any other way it sees
fit.  It could even eliminate it altogether if it could somehow detect that
results are never used, for example.

I think Sergio is saying is that this would be a great deal of work to add
that kind of knowledge into the compiler about common functions.

There have been cases where this was done, but naturally they are scarce
given the considerable compiler development required to support them.
First, most languages already have a set of intrinsic functions for basic
low level operations.  Bit shifts in Pascal are done that way, for example.
The LSHFT and RSHFT functions are known to the compiler and don't cause
library calls in most implementations.  My Pascal front end detects them and
a number of other intrinsic functions and writes out their resulting code.
LSHFT and RSHFT result in the << and >> operators if the result is written
in C.

Another case I remember is Silicon Graphics built in a few of the key
graphics calls of GL into their compiler.  Graphics functions are often
speed-critical since they can easily be executed millions of times while a
user is waiting for instant response.  A few of the GL calls were mapped
directly to I/O operations on their proprietary hardware and could be just a
few instructions.  A true call would have added at least as much overhead as
the target instructions, and would have prevented the compiler from doing
any optimization.

All in all I think intrinsic functions should be limited, especially when
common names are chosen.  It's dangerous to have a lot of reserved names in
a namespace the user can also create symbols in.  Of course you don't want
to have keyword bloat either, and the inline function syntax is convenient
for expressing a lot of things.  So as with everything, its a tradeoff.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\09@111939 by peter green

flavicon
face

> All in all I think intrinsic functions should be limited, especially when
> common names are chosen.  It's dangerous to have a lot of reserved names in
> a namespace the user can also create symbols in.
The way to get arround that is to give the intrinsic functions names in
the compiler private namespace (__ prefix in c) and then provide headers
with the compiler that use #define to map user visible names to the
internal names. Gcc does this for varargs support for example.

2009\07\10@012154 by William \Chops\ Westfield

face picon face

On Jul 9, 2009, at 7:28 AM, Olin Lathrop wrote:

> he wants things that look like library calls but that are really  
> intrinsic functions that the compiler understands natively.

This of course was very common in languages before (and other than)  
C.  I've opined before that part of C's success may have been due to  
having the language specification  completely separate from the  
language definition.  That wasn't true of Fortran, it's not true of  
Pascal (one of things that particularly annoyed me about  Pascal was  
that the language's built-in functions got to have more features than  
user-written functions.  Like variable numbers of arguments.)  Indeed,  
I think many languages got "bogged down" trying to define a "complete"  
set of useful library functions.

With C, the standardization of libraries was done separately, much  
later, and with (perhaps) more experience behind the decisions.  
Perhaps.  ("Posix")


> But didn't AT&T (owner of Bell Labs) sell Unix licenses? Not to the  
> general public, but still sell them?

I don't think so.  Not tell MUCH later, anyway (depending on who you  
mean by "not the general public.")  Until the mid-80s, unix was almost  
exclusively found only in universities and research institutes and  
such.  I'm not positive; prior to those times I worked at universities  
and research institutes :-)  Post mid-80s you had the famous "System  
V" (AT&T) vs BSD (Berkeley) wars.  The early 68000 systems (right  
about that same time) had real operating system difficulties.


> Maybe all of this WAS quite true a while ago, but nowadays we can  
> see that there is a LOT of #IFDEF in C sources to support multiple  
> platforms.

Actually, it's MUCH better than it used to be.  Get some code from  
about 1990, and it'll have conditionals for SYSV vs BSD vs (if you're  
luck) PC.  And it'll have LOTS of them, and they're UGLY (remember  
"near" and "far" for pre-386 intel CPUs?)  Post-standards, post-Posix,  
post-gcc there are comparatively minor differences for architecture  
(sometimes), plus what you might expect for difference windowing  
subsystems and so on.

Which is another point.  C *has* been getting better.   The compilers  
and error checking within the compiler has gotten better.  Compilers  
find errors that used to require "lint."  New functions have been  
defined that have better error checking capabilities (not "built it",  
but present) (alas, not always well-thought-out.  There was a whole  
generation of string functions that paid attention to "length" in  
rather useless ways.)   More than that, there's been so much USE of  
the languages that the "unwritten" standards have improved a great  
deal.  Compilers now post warnings about constructs like "if (a = b)",  
because programmers demand it.  They check the types of printf()  
arguments against the format descriptors (which is a really weird  
thing for a compiler that doesn't define printf() to do, but still  
rather useful.)  People are more careful about using explicitly  
defined data types.
That 1990 code wouldn't have had function prototypes.  It wouldn't  
have uint8_t.   It probably wouldn't have nice include files defining  
the APIs.
(Of course, your 1990 programs would have been a lot smaller than  
todays programs...)

BillW

2009\07\10@082358 by Gerhard Fiedler

picon face
William "Chops" Westfield wrote:

> I've opined before that part of C's success may have been due to
> having the language specification  completely separate from the
> language definition.  That wasn't true of Fortran, it's not true of
> Pascal (one of things that particularly annoyed me about  Pascal was
> that the language's built-in functions got to have more features than
> user-written functions.  Like variable numbers of arguments.)
> Indeed, I think many languages got "bogged down" trying to define a
> "complete" set of useful library functions.

I think this is something that made the porting of compilers rather
easy, and may be one of the reasons why C spread so (comparatively
easily) to many platforms. Especially true in the small micro and bare
metal world, where it's important that it's easy to replace the standard
library functions with custom implementations with little effort.

See for example printf and putch (used by printf) -- it's easy to adapt
the functionality of a standard function (printf), without having to
provide a custom implementation for it, by redefining another standard
function (putch) for your specific system. Which is easily possible
without modifying the compiler itself, even for the user.


>> But didn't AT&T (owner of Bell Labs) sell Unix licenses? Not to the  
>> general public, but still sell them?
>
> I don't think so.  Not tell MUCH later, anyway (depending on who you
> mean by "not the general public.")  Until the mid-80s, unix was
> almost exclusively found only in universities and research institutes
> and such.  

But how did those universities and research institutes get it? Did they
get it for free? I thought they had to buy it.


> They check the types of printf() arguments against the format
> descriptors (which is a really weird thing for a compiler that
> doesn't define printf() to do, but still rather useful.)  

Now /this/ is something that's closely related to what I was talking
about :)

Because how printf works is defined in the standard, even though it's
not part of the compiler, the compiler "knows" what printf is supposed
to do. And so it can do argument checking against the format string,
simply because this is defined in the standard. The compiler doesn't
have to have a built-in implementation of printf to do that -- it simply
will work with any standard implementation of printf.

Gerhard

2009\07\10@084538 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

> Gerhard Fiedler wrote:
>> You were talking about intent. For a normal library, the compiler
>> doesn't know about intent. For a library with a standardized
>> interface (for example, the C++ STL) the compiler does know about
>> intent.
>
> I think you guys are talking past each other.  I think what Gerhard is
> trying to say, but not doing a good job of it, ...

Of course I'm not doing a good job of it (I'm just Gerhard)... But
luckily I have Olin doing the job of telling the world what I /really/
want to say.

> ... is that he wants things that look like library calls but that are
> really intrinsic functions that the compiler understands natively.  

I don't "want" intrinsics nor has anything I wrote to do with
intrinsics. Has it occurred to you that if I wanted to talk about
intrinsic functions, I'd have done so?

I think I've been pretty clear about the fact that I was talking about
standard libraries (as the part you quoted spells out quite literally),
and in another part I mentioned that I'm talking about the compiler
seeing these libraries in source code form. No talk or thought of
intrinsics, ever, not even close.

> All in all I think intrinsic functions should be limited, especially
> when common names are chosen.  It's dangerous to have a lot of
> reserved names in a namespace the user can also create symbols in.  

In a sensibly designed language, the user wouldn't create names in the
same namespace where the standard library function names are.

Gerhard

2009\07\10@095324 by Terry Harris

picon face
On Fri, 10 Jul 2009 09:45:30 -0300, you wrote:

>I think I've been pretty clear about the fact that I was talking about
>standard libraries (as the part you quoted spells out quite literally),
>and in another part I mentioned that I'm talking about the compiler
>seeing these libraries in source code form.

Are you talking about effectively what Hi-Tech OCG does (or tries to)?

2009\07\10@100207 by olin piclist

face picon face
Gerhard Fiedler wrote:
> In a sensibly designed language, the user wouldn't create names in the
> same namespace where the standard library function names are.

That would be nice, but then you get the flip side of library functions
being more special than what the user can write.  That defeats one of the
things you said you liked about C, such as being able to create your own low
level functions (like PUTC or whatever) that are called by higher level
standard library functions like PRINTF.

None of the mainstream languages I've used had a reserved namespace for
standard library functions.  In fact, C is unusual with its notion of
standard library functions.  Some operating systems take care to use special
naming for their routines that are easily avoided by the user, but
unfortunately Unix and Windows are not among them.  The standard C library
routines and Unix routines are particularly bad in this regard.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\10@115134 by Dave Tweed

face
flavicon
face
olin_piclist@embedinc.com (Olin Lathrop) wrote:
> Gerhard Fiedler wrote:
> > In a sensibly designed language, the user wouldn't create names in
> > the same namespace where the standard library function names are.
>
> None of the mainstream languages I've used had a reserved namespace for
> standard library functions. In fact, C is unusual with its notion of
> standard library functions.

I think that's what's special about C relative to most other compiled
languages. Yes, there's a "standard C library", but it is in fact
completely distinct and separable from the language/compiler itself.
You can write major applications -- especially embedded applications --
in C without even once calling a standard library function. I know,
because I've done it. I've even replaced parts of "crt.s" (implicit code
in the library that sets up the environment for and supports the compiled
code, usually in assembly language) without fuss.

Some of the participants in this thread are downplaying the whole notion
of separate compilation with an explicit linking step that is actually a
fairly key part of C. This is what allows you, for example, to replace a
standard library function wtih a custom implementation, again, with little
to no fuss. Suppose you don't need the full-blown functionality of
printf(), with its dependency on the floating-point library, etc. Just
write your own and link it in ahead of the standard library and it will be
used instead.

> Some operating systems take care to use special naming for their routines
> that are easily avoided by the user, but unfortunately Unix and Windows
> are not among them. The standard C library routines and Unix routines
> are particularly bad in this regard.

Well, now you're conflating several issues, few of which have anything to
do with the actual definition of the language. Library naming issues are a
problem in any language.

Again, I think C does fairly well in this area because of the separate
compilation. You can easily limit the scope of any particular set of names
down to a particular file if you need to. Setting up the linking sequence
may then takes some care, and you have to learn how to avoid circular
dependencies at that level. But once a project gets to this level of
complexity, the issues are largely independent of the particular
language(s) in use.

-- Dave Tweed

2009\07\11@075955 by Gerhard Fiedler

picon face
Terry Harris wrote:

>> I think I've been pretty clear about the fact that I was talking
>> about standard libraries (as the part you quoted spells out quite
>> literally), and in another part I mentioned that I'm talking about
>> the compiler seeing these libraries in source code form.
>
> Are you talking about effectively what Hi-Tech OCG does (or tries
> to)?

Yes, in a way, and Microsoft, and probably a number of other vendors.
While standard C and C++ are based on the notion of completely
independent translation units, we're talking about how things could (or
should) be, and nothing hinders us to dream ahead a bit :)

Gerhard

2009\07\11@085454 by Gerhard Fiedler

picon face
Dave Tweed wrote:

> .....olin_piclistKILLspamspam.....embedinc.com (Olin Lathrop) wrote:
>> Gerhard Fiedler wrote:
>>> In a sensibly designed language, the user wouldn't create names in
>>> the same namespace where the standard library function names are.
>>
>> None of the mainstream languages I've used had a reserved namespace
>> for standard library functions. In fact, C is unusual with its
>> notion of standard library functions.

C++ has a namespace "std" for its standard library. The functions in
there are not treated any special (even though, in the sense of the
discussion around built-in vs library, they could be as the compiler can
assume it knows what they are doing). A user may define functions in the
std namespace, or override any of the library functions with his own
implementation. But no reasonable user will define his own symbols in
the std namespace. The namespace is there to avoid name clashes.

Java also has what you can call namespaces for their library functions
(mainly java and javax); they just call them packages. Works similar to
what I described above. It's not such a rare concept.

> I think that's what's special about C relative to most other compiled
> languages. Yes, there's a "standard C library", but it is in fact
> completely distinct and separable from the language/compiler itself.
> You can write major applications -- especially embedded applications
> -- in C without even once calling a standard library function. I
> know, because I've done it. I've even replaced parts of "crt.s"
> (implicit code in the library that sets up the environment for and
> supports the compiled code, usually in assembly language) without
> fuss.

I think pretty much every embedded C developer has done this at one
point or another. (Even though some standard library functions are so
small that deliberately avoiding calling them and instead doing it with
custom code doesn't buy much if anything.)

> Some of the participants in this thread are downplaying the whole
> notion of separate compilation with an explicit linking step that is
> actually a fairly key part of C. This is what allows you, for
> example, to replace a standard library function wtih a custom
> implementation, again, with little to no fuss. Suppose you don't need
> the full-blown functionality of printf(), with its dependency on the
> floating-point library, etc. Just write your own and link it in ahead
> of the standard library and it will be used instead.

Exactly. I think this flexibility is a good part of the popularity of C.


>> Some operating systems take care to use special naming for their
>> routines that are easily avoided by the user, but unfortunately Unix
>> and Windows are not among them. The standard C library routines and
>> Unix routines are particularly bad in this regard.
>
> Well, now you're conflating several issues, few of which have
> anything to do with the actual definition of the language. Library
> naming issues are a problem in any language.

There isn't really anything that would prevent a compiler vendor to ship
a library with its compiler where the Windows API is in namespace
"windows", the Posix API in a namespace "posix" and so on. They don't go
there, I think, because of the extra work required to wrap the Microsoft
etc. headers. (There is the functionality in the standard Microsoft C
headers that depends on the preprocessor, and the C/C++ preprocessor
doesn't know namespaces, so at least for C++, this would probably
require quite some work.)

Gerhard

2009\07\11@114916 by PPA

flavicon
face



Gerhard Fiedler wrote:
>
> ...
> For me, being able to compile the program in different versions of a
> compiler of the same vendor is the lowest level; I wouldn't even call
> this "portability", it's more like version compatibility. The next level
> is being able to compile on compilers from different vendors (on the
> same operating system); this maybe I'd start to call portability. Then
> come different operating systems and different target processors; here
> we get into what I call portability.
>
My assertions were a bit simplified; I'm sometimes a bit lazy on my
keyboard...
Sure that you are right on these points.

Gerhard Fiedler wrote:
>
> So how does this aspect look for Pascal? (This is not a rhetorical
> question; I really want to know from someone who uses Pascal portably.)
>
Is this irony? Well as I already said, you may use $ifdef constructs in "the
units that gather all portability sensitive parts" to manage portability,
say, from TP3 to Delphi (same vendor) or FPC (near compatible one) or Acme
Pascal or whatever one.
As I said no less no more than with C. OK, there may be more $ifdef than
#ifdef due to language compatibility, but these language differences are
very tight (more than in C witch may be qualified as nearly fully
"standard"); that's not "impossible", please stop saying that: that's just a
little bit harder than with C, no more. If you are used to do that that's
not really boring.

Gerhard Fiedler wrote:
>
> One application I work on has several 100kLOC that compiles fine on gcc
> and VC++ for Linux and Windows, with a very small and isolated part
> being compiler and platform specific. Recently we tested the Intel C++
> compiler for Windows, and the code compiled without any changes. (We
> dropped it, though, because the performance advantages were small, and
> the compile times were horrible.) Is this possible with Pascal -- taking
> such a complex application, pick another vendor's compiler, and it "just
> works"?
>
Not “it just works” for sure it needs often some work, but not so much as
you seem to want to make us to trust.
I've also managed several 100KLOC applications in Pascal. One was started in
TP3 under dos and now works in W32, on the latest compiler / windows
environment. I have to say that a big part of the functionalities are
skipped in the old dos version due to HW; I've not checked it recently but I
think that it would still compile with TPW for W3.11... Never tried on Kylix
or ThinkPascal that was not relevant but why not...
You have just to find a good method to be compatible, that's not very
complicated: just a matter of methodology. We are more used to do this in
Pascal since we have more issues to manage due to the lack of
standardization ;-)

Gerhard Fiedler wrote:
>
> Besides some odd vendors of small micro compilers, there aren't really
> any C dialects. The few there are are really niche thingies, mostly
> restricted to the PIC world (and maybe the one or other small micro, but
> I think the PIC compilers are worse than most others in this respect).
> In the great scheme of C, they almost play no role at all. Every
> compiler that wants to be worth its money has to be standard compatible,
> and therefore allows programming in standard C (or C++). Which is more
> common as you seem to think.
>
You said "odd vendors", "niche thingies", "almost no role at all".
There is always special needs and niches; people that are there would be
upset to read your comments; some niches may be less than a few percent of
percent of all the "great scheme of C world", but this may represent
thousands of people that are NOT playing "no role"; same as with Pascal or
even Cobol (there is even an object Cobol nowadays) or whatever...
On "has to be standard compatible" that's the point. Even if the standard is
not good enough? Even if you have a good idea that is non standard? Do you
think that in 2050 we will use the same old low level less common
denominator things? I hope not. A language should evolve or die, C as any
one; I think it will die because of these too low level standards that
nobody can jump off. Other languages are born, some died; see Cobol or
Fortran users that don't want to see the cliff edge: the final fall will be
hard - same for me with my Pascal and its childs? Can be, but in a long time
I hope; there's many choices nowadays; Java (a C child?) engines on chip
among other not so new things...

Gerhard Fiedler wrote:
{Quote hidden}

You're saying nice things and you say you don't like what has happened to it
but also you say wrong things. If you gave up on Pascal, maybe it is because
your job cannot be done with it at these times; that's not the case for
everybody so far. If there was another language that I can jump into as a
better replacement I would have done the break, but for now I've not
searched for because I don't need it. I've never used a C or C++ compiler at
all; some developments in VB / VB.NET because of an inevitable marketing
buzz touching some customers in the industrial world (Bad memories of these
dark ages)...

I'm not making another language war. As Olin, I'm speaking about methodology
and since I know what I say about Pascal, I compare with Pascal; if it was
another language I would have compared with it.
Also I'm not so defensive about Pascal; I know every limitation of this
language and every powerful thing as well.

I just don't like when people are saying that a language cannot do something
without arguments or even that it is dead without seeing/knowing all the
actual reality. This is surprising from somebody who comes from Pascal...

I may agree on discussions about why Pascal (or whatever language) does not
have found its place, not to discuss about not argued assertions.

Note that the beginning of the thread (not the OP) was on C good and bad
behaviors, on it's poor type checking among other things, not on if Pascal
didn't make it or was dead or not...
You wrote yourself some assertions that can be read as the beginnings of
another stupid language war by saying wrong things, so you cannot blame
anybody if you got answers on that, so please maybe we can let this aside
now.

On Microsoft vs. Borland, don't forget that Borland C/C++ compilers was far
better than Microsoft ones; all new improvements came from Borland;
Microsoft has copied everything, with the power of Microsoft, as they do
with other tools and good ideas, when finally they delivered their
"revolutionary" Visual tools... This is not technical, this is business and
in this domain they will stay #1 for a long time I guess.

Pascal side, Borland made a nearly de facto standard (the most used I
think); I don't understand why an official standardization was not done when
Borland was on top of the wave; then Pascal activity has decreased because
they had enough concerns to make survive their non-Pascal tools against the
power of Microsoft witch makes business on everything other than compilers.
An excellent technical level is not enough.
See what Microsoft is giving us at each new good business idea: we need to
come back to school to un-teach all what they teach us last time, new layers
that gives slower software even with a CPU power that doubles regularly...
Definitively not a good model for technical comparison of why something is
popular or not...



-----
Best regards,

Philippe.

http://www.pmpcomp.fr Pic Micro Pascal for all!
--
View this message in context: www.nabble.com/Re-using-BREAK-in-%27C%27-tp24256799p24441399.html
Sent from the PIC - [PIC] mailing list archive at Nabble.com.

2009\07\11@164055 by Gerhard Fiedler

picon face
{Quote hidden}

I was asking specifically about what I classified as "portability"
above, and not ironically at all. But you didn't answer the question.

Again: How does the portability aspect look with Pascal? Can you take
your sources and compile on Linux, Windows, Solaris, Unix? Can you
create executables for x86, x64, Itanium, ARM? Can you use a compiler
(on a platform that's already supported by your sources) from a
different vendor (that you didn't consider when writing your sources)
and with little or no changes compile your sources with it?

Is this possible? Is this actually being done with Pascal? If so, since
when?

(Again, this is not ironical. This is just not answered yet. I thought
this isn't really possible, in the sense that it's commonly being done.
You seem to say the contrary, but not with the clarity I'd like to
have.)


{Quote hidden}

Whoever wants to be upset about what I wrote here, be my guest :)

See, I'm one of those "niche C" users when I program in C on a PIC with
a not quite standard compliant C compiler. There's nothing wrong with
acknowledging that this is a tiny fraction of the usage of C, so when
talking about C in general, this simply doesn't count a lot.

But even then (in the PIC world, for example)... there are compilers
that are standard C, and there are compilers that aren't. And there are
compilers that are almost standard C with a few documented differences.
And there are compilers that call themselves C but are so far away from
the standard that they don't even list the differences.

So I have a choice... If I use one of the non-standard ones, I know that
I'm not programming in standard C, but in a proprietary language with
some similarity to standard C. This is different from not having a
standard at all -- /very/ different, IMO.

> On "has to be standard compatible" that's the point. Even if the
> standard is not good enough?

If the standard isn't good enough, it should be improved. This is what
for example is being done with the C and C++ standards. Not to
everybody's liking, of course... Some think more changes should be made,
some think that other changes should be made -- it's difficult to please
everybody :) And once there is a certain amount of source code out there
that relies on a standard, every improvement of that standard has to
take the issue of backwards compatibility into account.

But it's writing standard C++, for example, that allows me to pick any
old standard compliant compiler and compile my sources, and in general,
it'll just work.

(Repeating... I'm not saying C or C++ are good, or better than something
else. But people are saying that Pascal is better than C, yet C is more
popular, vastly more popular, than Pascal. There must be a reason... and
it's probably /not/ business. Microsoft didn't invent C, they're not
married to C, and Microsoft isn't a reason for C's popularity. The
calling convention for the Win16 API is the Pascal calling convention.
When they switched to the C calling convention for the Win32 API, they
probably followed instead of lead. There also seems to be a consensus
that Unix wasn't really commercial either.)

> Do you think that in 2050 we will use the same old low level less
> common denominator things?

I'm not sure, but I probably won't care. And I sure don't see what this
has to do with what I'm doing now. FWIW, I don't think that it'll be
that different. We'll just hobble along :)

> A language should evolve or die, C as any one; I think it will die
> because of these too low level standards that nobody can jump off.

Of course it will die, like every other language, sooner or later. But a
standard is not something that is necessarily contrary to evolution. And
the lack of a standard is not necessarily favorable for a language to
prosper.

> Other languages are born, some died; see Cobol or Fortran users that
> don't want to see the cliff edge: the final fall will be hard - same
> for me with my Pascal and its childs? Can be, but in a long time I
> hope; there's many choices nowadays;

I'm not sure, but I think Cobol is still alive and kicking. I may
remember this wrongly, but not so long ago I think I read that the
investment in Cobol programming is still among the top few. And I don't
think that all the program packages on university computers that are in
Fortran will be ported to something else any time soon.

Pascal won't die any time soon, either. That's not what I have been
writing about. The question is... how many shops do you know that hire
Pascal programmers (and pay them well)?

FWIW, I just ran a search on careerbuilder.com. Fortran: 13. Pascal: 15.
Delphi: 61. Cobol: 99. Python: 276. PHP: 1083. VB: 1173. C++: 1521. C#:
1892. Java: 3901. If this isn't "dead professionally", I don't know what
is. (I didn't search for C because unluckily "c" doesn't lend itself too
well for a keyword in a text-based search.)

> Java (a C child?) engines on chip among other not so new things...

I thought those Java chips are pretty much dead. Does anybody know
anything about them? Has anybody actually seen one in action? :)

> You're saying nice things and you say you don't like what has happened
> to it but also you say wrong things. If you gave up on Pascal, maybe
> it is because your job cannot be done with it at these times; that's
> not the case for everybody so far.

Not for everybody, but check out the job market for programmers and tell
me that there is a substantial market for Pascal programmers without
blushing :)

> I just don't like when people are saying that a language cannot do
> something without arguments or even that it is dead without
> seeing/knowing all the actual reality. This is surprising from
> somebody who comes from Pascal...

I have asked you, and you haven't responded. I asked about one Pascal
source compiling for different target operating systems, different
target processors -- and all you came up with was porting something from
MS-DOS through Win3.11 to Win32, with the MS-DOS (and Win3.11?) code not
having the same functionality as the Win32 code. This is not what I
meant; I meant a broader scope.

The other question is, and that's the real issue here, why is Pascal
dead in professional programming? By "dead" I don't mean that nobody
uses it, but for somebody's sake, 6 out of 8846 posted IT jobs on
careerbuilder.com mention Pascal, 19 mention Delphi, whereas 672 mention
C++ and 1666 mention Java... for me, that's "dead" as a general purpose
language.


> I may agree on discussions about why Pascal (or whatever language)
> does not have found its place,

I'd like to hear what you think why Pascal is so unpopular.

> Note that the beginning of the thread (not the OP) was on C good and
> bad behaviors, on it's poor type checking among other things, not on
> if Pascal didn't make it or was dead or not...

The thread has evolved, as with you answering me.

> You wrote yourself some assertions that can be read as the beginnings
> of another stupid language war by saying wrong things,

What's wrong in what I said?

> On Microsoft vs. Borland, don't forget that Borland C/C++ compilers
> was far better than Microsoft ones; all new improvements came from
> Borland; Microsoft has copied everything, with the power of
> Microsoft, as they do with other tools and good ideas, when finally
> they delivered their "revolutionary" Visual tools... This is not
> technical, this is business and in this domain they will stay #1 for
> a long time I guess.

This is exactly what I'm saying. Borland didn't have the economic power
to do it the same way as Microsoft, so they should've done it
differently. Trying to be the only player (by not standardizing the
language) only works well if you can do it like Microsoft and really be
the only player. (And even Microsoft standardized .NET and C#, for
whatever this is worth... :)

> Pascal side, Borland made a nearly de facto standard (the most used I
> think); I don't understand why an official standardization was not
> done when Borland was on top of the wave; then Pascal activity has
> decreased because they had enough concerns to make survive their
> non-Pascal tools against the power of Microsoft witch makes business
> on everything other than compilers. An excellent technical level is
> not enough.

Exactly what I'm talking about.

> See what Microsoft is giving us at each new good business idea: we
> need to come back to school to un-teach all what they teach us last
> time, new layers that gives slower software even with a CPU power
> that doubles regularly... Definitively not a good model for technical
> comparison of why something is popular or not...

There is no "technical comparison why something is popular". There are
technical comparisons, and there is the attempt of finding out why some
things are popular and others not, and how this relates to the technical
comparisons.

But IMO the popularity of C has not much to do with Microsoft, other
than that they provide a decent compiler for Windows that's among the
most popular compilers on Windows. Microsoft's compiler is probably very
rarely used to compile C sources.

Gerhard

2009\07\11@174333 by olin piclist

face picon face
Gerhard Fiedler wrote:
> (Repeating... I'm not saying C or C++ are good, or better than
> something else. But people are saying that Pascal is better than C,

In a technical sense.  And Pascal is only one example.  I'm not pushing
Pascal, only trying to get everyone to realize how awful C is.

> yet C is more popular, vastly more popular, than Pascal. There must
> be a reason...

Of course, but since that reason is not technical superiority it is
irrelevant.  People use C because they have to, myself included.  There are
legitimate reasons to use C today, like it's what available employees know,
because new code has to be added to existing C code, because of wider
poratbility, because its the language of the available compilers for a
particular platform, because the customer insists on it regardless of why,
etc.  I think we all agree C has reached critical mass by a long shot.

The main point is that C is not technically superior.  In fact it's rather
inferior to better compiled languages like several of the Pascal variants
from the 1980s.  There is a serious cost in developing in C.  While none of
this is going to change that people continue to develop in C for all the
other reasons cited above, I'll be happy for now if only they grumble "I
have to use this $%&*@# C again, I wish I could use something better"
everytime they are forced to do so.  Things aren't going to change until the
general consensus is "C sucks".  Some are already there, but too many
sheeple aren't yet.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\11@180137 by Isaac Marino Bavaresco

flavicon
face
Gerhard Fiedler escreveu:
> I have asked you, and you haven't responded. I asked about one Pascal
> source compiling for different target operating systems, different
> target processors -- and all you came up with was porting something from
> MS-DOS through Win3.11 to Win32, with the MS-DOS (and Win3.11?) code not
> having the same functionality as the Win32 code. This is not what I
> meant; I meant a broader scope.

For simple console application, one should be able to just recompile his
code across DOS, Windows, Linux, etc. using C or Pascal (FreePascal).

Once you start speaking of GUI applications, things get more
complicated, even for C/C++.

There is wxWidgets (<http://www.wxwidgets.org/>), a free software
application framework available for lots of platforms.

Quote from the home page:
"wxWidgets lets developers create applications for Win32, Mac OS X,
GTK+, X11, Motif, WinCE, and more  using one codebase. It can be used
from languages such as C++, Python, Perl, and C#/.NET. Unlike other
cross-platform toolkits, wxWidgets applications look and feel native.
This is because wxWidgets uses the platform's own native controls rather
than emulating them. It's also extensive, free, open-source, and mature.
Why not give it a try, like many others have?"

It works also with Win64, Linux, NetBSD, FreeBSD, OpenBSD, Solaris,
HP-UX, AIX and more.

It has bindings for lots of languages: wxAda, wxBasic, C++ (native),
wxD, wxDelphi/wxPascal, wxErlang, wxEuphoria, wxHaskell, wxJava, jwx!
(also Java), GLUEscript(JavaScript), wxLua, wxMax, wxNet, wxPerl,
wxPike, wxPython, wxRuby, wxSqueak



Regards,

Isaac

__________________________________________________
Faça ligações para outros computadores com o novo Yahoo! Messenger
http://br.beta.messenger.yahoo.com/

2009\07\11@183929 by Tamas Rudnai

face picon face
Guys I totally lost the line now. We were already talking about library and
compiler differences, and that it is no matter if that is C or Pascal when
we want to compile a code into different platforms. I am not sure why are we
discussing about this even further? That is not a question that we could
develop in Pascal multiplatform, the original question was why C is used
nowadays instead?

Tamas



On Sat, Jul 11, 2009 at 11:01 PM, Isaac Marino Bavaresco <
EraseMEisaacbavarescospam_OUTspamTakeThisOuTyahoo.com.br> wrote:

{Quote hidden}

>

2009\07\14@170156 by sergio masci

flavicon
face


On Thu, 9 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

Ok I've read and re-read your posts trying to understand what it is that
you are trying to say in order to better understand how I am failing to
get my point across.

You seem to be saying that provided a set of libraries are well written
and available in source form to the compiler that it can compile these
together with the user program and (given that the compiler is
implemented well enough by the compiler writers) that the compiler should
be able to extract enough information from all the combined source code
to generate a resulting executable that is as good as one that would be
generated if the language had more built-in features such as STRING,
LIST, DYNAMIC ARRAYS etc. Furthermore that the compiler should be able
to catch the same kind of bugs in both cases.

Ok given an infinately fast build system with an infinate amount of RAM
and a mega complex compiler that looks for every possible combination of
source code - breaking it down and rearrangeing everything in an attempt
to understand every possible consequence of every combination of
statements given - then yes I would agree. However this is just
completely impracticle.

As an example lets just consider how many different ways you can append
a number (as a string) to another string:

Here's a simple bit of code:

       char        str[100];
       char        buff[16];
       int        j, len;


       strcpy(str, "hello world");

       lne = strlen(str);

       sprintf(buff, "%d", j);

       strcpy(str+len-1, buff);


another way of doing this would be

       strcpy(str, "hello world");

       sprintf(buff, "%d", j);

       strcat(str, buff);


yet another way would be

       sprintf(str, "hello world%d", j);


and another way would be

       strcpy(str, "hello world");

       sprintf(buff, "%d", j);

       lne = strlen(str);

       strcpy(str+len-1, buff);


and another

       strcpy(str, "hello world");

       sprintf(buff, "%d", j);

       strcpy(str+strlen(str)-1, buff);


and another

       strcpy(str, "hello world");

       sprintf(buff, "%d", j);

       lne = strlen(str);

       str += len-1;

       strcpy(str, buff);


and another

       strcpy(str, "hello world");

       str += sprintf(buff, "%d", j);

       str--;

       strcpy(str, buff);


and another

       strcpy(str, "hello world");

       strcpy(str + sprintf(buff, "%d", j) - 1, buff);


So if I tell the compiler that all the above is simply a way of
appending the ASCII representation of a number to a string what should
it make of the following incorrect piece of code:

       strcpy(str, "hello world");

       sprintf(buff, "%d", j);

       strcpy(str+len-1, buff);


How is the compiler supposed to know that I am trying to append the
ASCII representation of a number to a string and I got it wrong? In this
case is the compiler just supposed to take the code I've written as
correct (because it doesn't recognise what I actually wanted to do) and
so generate an executable with a bug?

if strings were built into the language we might instead write:

       str = "hello world" + string(j)

Wow, how cool is that! So easy to write, so easy to understand when you
come back to it years later. Even a dumb compiler would have no trouble
understanding this statement, and a clever compiler would be able to put
some nice optimisations in place. And we even got rid of the huge printf
library as a side effect.

I'm pretty sure that at this point you will (as others have done) start
telling me that I should be using other functions to "encapsulate" this
fragment of "knowledge". Ok so you encapsulate it, you produce yet
another standard library function but you still have the same problem -
the compiler still needs to be able to understand this fragment if it is
to have the same capabilities as a compiler that has this as a built-in.
The only thing you achive by placing this fragment in a function is to
reduce the possibility that someone will rewrite the code incorrectly.
Note here that I say reduce and not eliminate. A user would still rather
write a couple of lines of code than waste time looking up a trivial
function in an over inflated library. You need to give the user a real
incentive to use this new library function. On the other hand if this
fragment of functionality is built into the language (and compiler) and
is itself a sub-set of a basic component (feature) of the language (e.g.
string handling) then the user will embrace it sooner or later because
he/she will be constantly exposed to this feature and gradually progress
from using basic parts of this feature to the more complex aspects of
it.

Another problem with using functions as opposed to built-ins (call them
features if you like) is where you need to distinguish between the
overloaded functions and the parameters of both are of the same type.
Then you are stuck and need to resort to using different names for the
functions whereas it would be more natural to use one consistant name
(hance the function overloading in the first place).

So say for example I wanted to extract a sub-string from a string. I could
have a function:

       // create a new string from 'pos1' to the end of the string
       str2 = substr(str1, pos1);

       // create a new string from 'pos2' to the start of the string
       pos2 = -pos;
       str2 = substr(str1, pos2);

       // create a new string from 'pos1' to 'pos2'
       str2 = substr(str1, pos1, pos2);


but what if I wanted to extract a sub-string that was a given length
rather than bewteen two positions. I couldn't write

       str2 = substr(str1, pos1, len);


because this would be seen by the compiler as

       substr(char *, int, int);


which also corresponds with the above use for

       str2 = substr(str1, pos1, pos2);


I could have the equivalent functions

       // create a new string from 'pos1' to the end of the string
       str2 = substr_to_end(str1, pos1);

       // create a new string from 'pos1' to the start of the string
       str2 = substr_from_start(str1, pos1);

       // create a new string from 'pos1' to 'pos2'
       str2 = substr(str1, pos1, pos2);

       // create a new string from 'pos1' of length 'len
       str2 = substr_lengeth(str1, pos1, len);



But this comes with it's won hazards, mainly that the user could VERY
easily write:

       str2 = substr(str1, pos1, len);

where he actually needed:

       str2 = substr_lengeth(str1, pos1, len);


Realistically how is a conventional compiler (one that is not mega
complex and running on an infinately fast build machine with an infinate
amount of RAM) going to spot this type of mistake without adding a ton
of attributes to the function prototype?

If strings were built in we could simply say something like

       str2 = substr str1 from pos1 to pos2

or

       str2 = substr str1 from pos1 to end

or

       str2 = substr str1 from pos1 length len




I keep talking about the compiler understanding the intent of the
programmer and you keep saying that a compiler could do this if it had
all the source available. I wonder if what you are really saying is that
the compiler can do more error checking and optimisation because it has
all the source rather than pre-compiled libraries? Because this is
definately not what I'm getting at by "intent". What I mean is (as
above) where the compiler is able to recognise a fragment of code as
meaning "do something special" (such as append one string to another).

This (recognising intent) is easy to do if the language has an
understanding of common basic types such as strings, lists etc but
increadibly hard to do if it does not.

I talk about the brick wall between the compiler and the libraries and
you respond with "make the source of the libraries available". Making
the source available still means that the compiler needs to do a hell of
a lot of work to to try to understand the intend behind each and every
function. How for example would the compiler recognise a function whose
purpose it is to seach a list for a particular string and if it does not
exist then insert a copy of the string into the list in alphabetic
order?

Look at the way programs are commented now so that other programmers
coming along later can understand what a fragment of code is actually
trying to achive. There again we have a brick wall between the comments
and the compiler. The comments don't actually help the compiler verify
or optimise the code.

What we need are features that make it easier for the programmer to
understand the code. Features that cut down on the low level mundane
error prone repetetive code that the programmer needs to write. Features
that allow some of the code and comments to merge - making it hard for
incorrect comments to be left in place and making it easy to see what
the source code actually means. Does this all sound familiar? Isn't this
one of the arguments made when trying to persuade users to move from
assembler to high level languages.

Look at a small fragment for inserting an item into a list:

       item = &root;

       while (*item != NULL)
       {
               if (strcmp((*item)->key, key) > 0)
               {
                       temp = *item;
                       *item = new_item(key);
                       item = &(*item)->next_item;
                       *item = temp;

                       break;
               }

               item = &(*item)->next_item;
       }

re-written another way:

       item = &root;

       while (*item != NULL)
       {
               if (strcmp((*item)->key, key) > 0)
               {
                       break;
               }

               item = &(*item)->next_item;
       }

       if (*item != NULL  &&
           strcmp((*item)->key, key) != 0)
       {
               temp = *item;
               *item = new_item(key);
               item = &(*item)->next_item;
               *item = temp;
       }


Now try writing a rule that understands the above two small
fragments as two identical units.

Friendly Regards
Sergio Masci

2009\07\14@171332 by sergio masci
flavicon
face


On Thu, 9 Jul 2009, Olin Lathrop wrote:

{Quote hidden}

Thank you Olin, I had considered that Gerhard was maybe talking about
intrinsic functions. Originally I thought he was saying that the language
should allow you to give the compiler enough info on a nonmal
(non-intrisic) function to be able to use it the same way. Then I cottened
on to the fact that what he was actually saying is that if a compiler
could analyse all the source (including that of the libraries) then it
would be able to extract all the info needed to make a non-intrinsic
function intrinsic.

Friendly Regards
Sergio Masci

2009\07\14@173216 by sergio masci

flavicon
face


On Thu, 9 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

No Gerhard the fundamental principle is still indentical - you switch
task contexts. Wheather this means that you need to completely save one
CPU context and load another OR you arrange for the the task contexts to
co-exist and simply switch between them is upto the implementor.

Having multiple CPUs each potentially executing a different task where the
task contexts are not protexted from one another (as in a 628) is no
differnt to having an interrupt coming along and modifying variables
belonging to a task when it is unsafe.

Friendly Regards
Sergio Masci

2009\07\14@231454 by Gerhard Fiedler

picon face
sergio masci wrote:

> Ok I've read and re-read your posts trying to understand what it is
> that you are trying to say in order to better understand how I am
> failing to get my point across.

I resisted the temptation to quote all the stuff again... :)

{Quote hidden}

Not quite. Firstly, I was talking about /standard/ libraries, where the
compiler also "knows" what the functions are supposed to do (because
it's defined in the same place where is defined what the compiler itself
is supposed to do).

> As an example lets just consider how many different ways you can
> append a number (as a string) to another string:

Secondly, this was (in my mind, at least) a discussion /only/ about the
merits of features built-in (to the compiler) versus implemented in a
(standard) library. This is not a discussion about the shortcomings of C
(or about whether or not XSCB is better than C :).

So I snipped the following... all examples of how something can be done
in C. Whether something is possible or not in C isn't really relevant to
our discussion, I think.

> if strings were built into the language we might instead write:
>
>        str = "hello world" + string(j)

See, in C++ for example, strings are /not/ built into the language, and
you can write pretty much exactly this. (Not with the std::string, but
if you extend it a bit, you can, so in the case of C++ it's not really a
question whether or not it can be done with strings in a library but
whether the library definition is sufficient.)

I agree that the lack of a built-in decent string type in C can be a
pain, especially in terms of syntax. OTOH, I bet your strings are 8-bit
strings. Now what if I need to handle Unicode strings? Wait for a
compiler upgrade? And what if that compiler upgrade doesn't handle the
Unicode encoding I need?

> And we even got rid of the huge printf library as a side effect.

If that's a concern, HiTech for example parses all printf strings in the
whole application and based on that decides what to include into printf.
Since printf is a /standard/ library function, they can do this -- and I
still can override theirs with mine, or make theirs work with my own
putch function. I don't know how exactly they do it, but it doesn't
really matter whether they have a bunch of configuration parameters for
a printf library function and the compiler sets the configuration
parameters accordingly, or whether their printf function is implemented
in the compiler itself. It doesn't matter because it's a standard
library, and as long as their compiler behaves accordingly (and lets me
override their function with my own if I want), it's all fine.


> A user would still rather write a couple of lines of code than waste
> time looking up a trivial function in an over inflated library. You
> need to give the user a real incentive to use this new library
> function. On the other hand if this fragment of functionality is
> built into the language (and compiler) and is itself a sub-set of a
> basic component (feature) of the language (e.g. string handling) then
> the user will embrace it sooner or later because he/she will be
> constantly exposed to this feature and gradually progress from using
> basic parts of this feature to the more complex aspects of it.

It's the number of symbols and their structure that makes a feature set
"over inflated". IMO it doesn't make a difference whether you have 5000
symbols in a library and people think it's too much or whether you have
5000 symbols in a compiler and people think it's too much.


(Snipped prelude to substr argument.)

{Quote hidden}

This is a simple matter of syntax. You don't do much more here than
comparing C-style syntax with BASIC-style syntax. A matter of taste...
The BASIC-style syntax uses "substr ... from ... to" and "substr ...
from ... length". A similar C-style syntax could use substr_from_to and
substr_from_len -- or any number of similar variants. Then there's the
LISP syntax, and a few others. I don't see what this has to do with
built-in vs library.


> I keep talking about the compiler understanding the intent of the
> programmer and you keep saying that a compiler could do this if it
> had all the source available.

Nope, I never said that. I said that if we are talking about /standard/
libraries, the compiler "knows" the intent of the /standard/ library
functions just as well as it knows the intent of the built-in
constructs; both are defined in the same standard.

> I wonder if what you are really saying is that the compiler can do
> more error checking and optimisation because it has all the source
> rather than pre-compiled libraries?

What I'm saying is that if it has the intent /and/ the source (the
implementation), it can apply both for (usually different, and
complementary) optimizations. Not that different from what it can do for
built-in constructs.

> This (recognising intent) is easy to do if the language has an
> understanding of common basic types such as strings, lists etc but
> increadibly hard to do if it does not.

You seem to miss the point that the /intent/ of the functions in
standard libraries is just as defined as the intent of language
constructs built into the compiler.


> I talk about the brick wall between the compiler and the libraries and
> you respond with "make the source of the libraries available".

No. I say consider that the library is a /standard/ library. Adding the
source code is in addition, so that the compiler not only "knows" the
intent, but also sees the implementation.

> How for example would the compiler recognise a function whose purpose
> it is to seach a list for a particular string and if it does not
> exist then insert a copy of the string into the list in alphabetic
> order?

Because this intent is defined in the standard.


> Look at a small fragment for inserting an item into a list:
>
> [snipped C code]
>
> Now try writing a rule that understands the above two small
> fragments as two identical units.

Look at the C++ standard library definition for std::list::insert, for
example. It contains a definition that allows each C++ compiler to
"understand" what a call to std::list::insert is supposed to do.

Gerhard

2009\07\14@232128 by Gerhard Fiedler

picon face
sergio masci wrote:

> Thank you Olin, I had considered that Gerhard was maybe talking about
> intrinsic functions.

Why don't you just read what I wrote rather than trying to guess? I
pretty much wrote what I meant. If I had meant intrinsics, I'd have
written about intrinsics.

> Then I cottened on to the fact that what he was actually saying is
> that if a compiler could analyse all the source (including that of
> the libraries) then it would be able to extract all the info needed
> to make a non-intrinsic function intrinsic.

No, I never said this. I said that if a library is a /standard/ library
(and I have mentioned this word "standard" a few times; you didn't seem
to pick up on this), the compiler "knows" about the intent of a
function, not any different than it "knows" about the intent of a
language construct. (The intent is a concept that you brought in as
being important, and I don't see what's the difference between a
standardized built-in construct and a standardized library in terms of
"knowing" about the intent.)

The thing about having the lib available in source code is in addition
to this, and about other optimizations (probably lower level than those
that deal with intent).

Gerhard

2009\07\15@010414 by William \Chops\ Westfield

face picon face

On Jul 14, 2009, at 8:21 PM, Gerhard Fiedler wrote:

> If I had meant intrinsics, I'd havewritten about intrinsics.

> I said that if a library is a /standard/ library (and I have  
> mentioned this word "standard" a few times; you didn't seem to pick  
> up on this),

What exactly do you see as the difference between an "intrinsic"  
function and a Standard library function?  I mean sin() is a standard  
library function in C, but an intrinsic function in fortran/pascal/
etc, right?

Are you saying that a C compiler could understand that "sin()" is  
standard and generate straight math processor instructions (intel FP  
has had a FSIN instruction since forever) rather than a library call?  
(assuming that it "knows" that the instructions and the library are  
supposed to generate the same results...)

BillW

2009\07\15@025216 by Tamas Rudnai

face picon face
On Wed, Jul 15, 2009 at 4:14 AM, Gerhard Fiedler <listsspamspam_OUTconnectionbrazil.com
> wrote:

> Not quite. Firstly, I was talking about /standard/ libraries, where the
> compiler also "knows" what the functions are supposed to do (because
> it's defined in the same place where is defined what the compiler itself
> is supposed to do).


Now I completely lost. Are you saying that a C compiler recognizes specific
function calls like printf and when you write printf("hello %s", "world");
it realizes that a puts("hello world"); would be much cheaper as part of the
optimization? Or you are talking about intrinsic functions within the
library where it still uses the printf function but makes all the code
optimizations as the library function was written in the place where it was
called from?


{Quote hidden}

That's because of the operator '+' can be overloaded in a string type
object. In laguages like Pascal the string has a different structure than in
the ANSI C, so you have the actual length of the string at the very
beginning of the string  buffer (it is like a minimalistic buffer header).
That makes it possible to implement string manipulations faster and easier
-- therefore a string concatenation is an easy task by language definition.



> I agree that the lack of a built-in decent string type in C can be a
> pain, especially in terms of syntax. OTOH, I bet your strings are 8-bit
> strings. Now what if I need to handle Unicode strings? Wait for a
> compiler upgrade? And what if that compiler upgrade doesn't handle the
> Unicode encoding I need?


I agree with you that in C++ they put these things in a way that it can be
extended easily -- especially if the string was handled by STL. In the other
hand on an x86 PC on the compiler side they only needed to change minor
things, like replacing "rep movsb"  to "rep movsw" and problem solved --
while in C++ these things are function calls to the overloaded functions
from the string class.



> If that's a concern, HiTech for example parses all printf strings in the
> whole application and based on that decides what to include into printf.
> Since printf is a /standard/ library function, they can do this -- and I


I think that's a normal dead code elimination -- which you can do that with
either unused object code within a library or with intrinsic type of
functions within the object code. The first technique is rather old one --
in Turbo Pascal for example the linker never put a function from an object
file that was never been accessed to.

Also I am not sure with HiTech but in many embedded C compiler you can tell
which type of printf do you want to use within your application (there are
some minimalistic version, with some restricted version like no float types
and the full version). Hang on a minute, are you saying the HiTech
automatically chooses the smallest/fastest but still functional one when you
are compiling your application?

Tamas

2009\07\15@043502 by sergio masci

flavicon
face


On Wed, 15 Jul 2009, Gerhard Fiedler wrote:

> sergio masci wrote:
>
> > Thank you Olin, I had considered that Gerhard was maybe talking about
> > intrinsic functions.
>
> Why don't you just read what I wrote rather than trying to guess? I
> pretty much wrote what I meant. If I had meant intrinsics, I'd have
> written about intrinsics.

Hi Gerhard,

Did I upset you? I didn't mean to. I was not trying to "guess" what you
were thinking either, I was trying to understand what you were saying. In
any form of comunication there will be interpretation. You will know what
it is that you are saying. Somethings you will not say because you will
take it for granted that I will infer them (and I may not or I may infer
something else). Somethings you will say something that will have a
particular meaning to you and a slightly different meaning to me.
Sometimes two people can have a discussion, agree on what needs to be
done, leave the discussion and do something the other person was not
expecting.

What I was trying to do was understand "exactly" what you meant rather
than just trying to force you to accept my ideas.

{Quote hidden}

about intrinsic functions. Yes the function is defined in a library but
the compiler also knows about the intent of the function. The intent is
seperate from the definition since and is included by the compiler writer
directly into the compiler. The definition of the function is provided by
someone else (library implementor?) and may even be at odds with what the
compiler understands it to be.

Friendly Regards
Sergio Masci

2009\07\15@043722 by sergio masci

flavicon
face


On Tue, 14 Jul 2009, William "Chops" Westfield wrote:

{Quote hidden}

This is what I now understand Gerhard to mean.

Friendly Regards
Sergio Masci

2009\07\15@054832 by sergio masci

flavicon
face


On Wed, 15 Jul 2009, Gerhard Fiedler wrote:

> sergio masci wrote:
>
> > Ok I've read and re-read your posts trying to understand what it is
> > that you are trying to say in order to better understand how I am
> > failing to get my point across.
>
> I resisted the temptation to quote all the stuff again... :)

I felt it was necessary because several days have gone by between
your post and my response.

{Quote hidden}

It is now clear to me that you are talking about intrinsic functions. Yes
the function is defined in a /standard/ library but the compiler also
knows about the function independently of the library.

>
> > As an example lets just consider how many different ways you can
> > append a number (as a string) to another string:
>
> Secondly, this was (in my mind, at least) a discussion /only/ about the
> merits of features built-in (to the compiler) versus implemented in a
> (standard) library. This is not a discussion about the shortcomings of C
> (or about whether or not XSCB is better than C :).

Yes I agree this discussion is only about the merits of built-in features
versus library functions. I do use examples written in C because many
people on this list can relate to them and C uses library functions
extensively to overcome its shortcomings.

{Quote hidden}

But the C++ compiler understands what is going on here even less. We now
end up adding even more run time overheads just to make the source code
look better.

> I agree that the lack of a built-in decent string type in C can be a
> pain, especially in terms of syntax. OTOH, I bet your strings are 8-bit
> strings. Now what if I need to handle Unicode strings? Wait for a
> compiler upgrade? And what if that compiler upgrade doesn't handle the
> Unicode encoding I need?
>

Yes I understand your point of view, but 8-bit strings are still very
useful even if you need to use Unicode in the same program. Just like
integers are very useful even though you might need to use floating point.

Anyway having built-in features doesn't stop you adding sets of functions
as libraries.

{Quote hidden}

GCC allows you to add an attribute to a function so that the compiler will
check the type of an actual parameter against a format string.

{Quote hidden}

Agreed.

{Quote hidden}

It makes a difference if you consider that each statement helps the
compiler understand what the perpose of a variable is. In the above
example 'length len' within the 'substr' statement allows the compiler to
understand that 'len' is being used to manipulate strings in this fragment
so it WOULD be able to help me catch a simple error such as:

       for (j=0; j<len; j++)
       {
               len2 = strlen(arr[j]);

               arr2[j] = substr(arr[j], 0, len-2);
       }

>
> > I keep talking about the compiler understanding the intent of the
> > programmer and you keep saying that a compiler could do this if it
> > had all the source available.
>
> Nope, I never said that. I said that if we are talking about /standard/
> libraries, the compiler "knows" the intent of the /standard/ library
> functions just as well as it knows the intent of the built-in
> constructs; both are defined in the same standard.

Ok I missinterpreted what you said - sorry :)

>
> > I wonder if what you are really saying is that the compiler can do
> > more error checking and optimisation because it has all the source
> > rather than pre-compiled libraries?
>
> What I'm saying is that if it has the intent /and/ the source (the
> implementation), it can apply both for (usually different, and
> complementary) optimizations. Not that different from what it can do for
> built-in constructs.

Ok, but you really are talking about intrinsics as I understand them with
the addition of a standard library function for each intrinsic.

>
> > This (recognising intent) is easy to do if the language has an
> > understanding of common basic types such as strings, lists etc but
> > increadibly hard to do if it does not.
>
> You seem to miss the point that the /intent/ of the functions in
> standard libraries is just as defined as the intent of language
> constructs built into the compiler.

I understand what you mean by this now.

>
>
> > I talk about the brick wall between the compiler and the libraries and
> > you respond with "make the source of the libraries available".
>
> No. I say consider that the library is a /standard/ library. Adding the
> source code is in addition, so that the compiler not only "knows" the
> intent, but also sees the implementation.

got you. intrinsic + library

{Quote hidden}

I will look at this. Can you point me at a specific doc and library so
that I can be sure to look at exactly what you are looking at.

Friendly Regards
Sergio Masci

2009\07\15@073000 by olin piclist

face picon face
Gerhard Fiedler wrote:
> I resisted the temptation to quote all the stuff again... :)

It really has been confusing trying to figure out what exactly your point
is.

> Not quite. Firstly, I was talking about /standard/ libraries, where the
> compiler also "knows" what the functions are supposed to do (because
> it's defined in the same place where is defined what the compiler itself
> is supposed to do).

But that's exactly what intrinsic functions are, which you strongly claimed
you weren't talking about when I suggested that's what you might mean.  Now
I am (and I think Sergio too) really confused.  How is what you mean not
intrinsic functions?

> I agree that the lack of a built-in decent string type in C can be a
> pain, especially in terms of syntax. OTOH, I bet your strings are 8-bit
> strings. Now what if I need to handle Unicode strings?

Tell your customers to use ASCII like civilized people ;-)

> Wait for a
> compiler upgrade? And what if that compiler upgrade doesn't handle the
> Unicode encoding I need?

Note that you're no worse off if it doesn't support the character
representation you like.  The reverse can also be a pain, like Java where
everything is one of those unicode thingies.  Maybe that's nice if you want
to appease some illiterate in a distance jungle somewhere, but it's a hassle
if you want to send a stream of 8 bit characters to a microcontroller.  And
now even 65K glyphs are apparently not enough.  Is this nonsense ever going
to end?

>> And we even got rid of the huge printf library as a side effect.
>
> If that's a concern, HiTech for example parses all printf strings in the
> whole application and based on that decides what to include into printf.

There are usually several ways around a single problem, but I'm not sure
what exactly your point is here.

> Since printf is a /standard/ library function, they can do this -- and I
> still can override theirs with mine, or make theirs work with my own
> putch function. I don't know how exactly they do it, but it doesn't
> really matter whether they have a bunch of configuration parameters for
> a printf library function and the compiler sets the configuration
> parameters accordingly, or whether their printf function is implemented
> in the compiler itself. It doesn't matter because it's a standard
> library, and as long as their compiler behaves accordingly (and lets me
> override their function with my own if I want), it's all fine.

So it sounds like you want a bunch of intrinsic functions (which represent a
large amount of compiler work), but have any optimization defeated and your
own function called if you define one?

> It's the number of symbols and their structure that makes a feature set
> "over inflated". IMO it doesn't make a difference whether you have 5000
> symbols in a library and people think it's too much or whether you have
> 5000 symbols in a compiler and people think it's too much.

I think part of the point is that certain features, like the string handling
Sergio described, require a lot less special syntax when built in than they
would require special functions if "built in" that way.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\15@074520 by olin piclist

face picon face
sergio masci wrote:
>> Are you saying that a C compiler could understand that "sin()" is
>> standard and generate straight math processor instructions (intel FP
>> has had a FSIN instruction since forever) rather than a library call?
>> (assuming that it "knows" that the instructions and the library are
>> supposed to generate the same results...)
>
> This is what I now understand Gerhard to mean.

I think now that he wants this, which is what a intrisic function is whether
he likes to call it that or not, but also wants to override it if he defines
such a function himself.  I think languages that have intrinsic functions
are split on how this is handled.

I can see the point of generating a error if you try to define your own
routine with the name of a intrinsic function.  Never letting you redefine a
intrinsic is the safe thing to do.  It avoids nasty problems of scope, which
could be difficult to know at link time where some of this may have to be
resolved.  For example, your application may want a specialized version of a
intrinsic function, but its not clear what version a routine deep in a
library ends up getting when you may not even be aware the library used the
particular intrinsice.  In some cases, like if you are making use of special
hardware you know is present, you may want the library routines to use your
version.  In other cases the library may work incorrectly with your version,
if you took a few short cuts to gain speed, for example.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\15@084015 by Gerhard Fiedler

picon face
Tamas Rudnai wrote:

>> Not quite. Firstly, I was talking about /standard/ libraries, where
>> the compiler also "knows" what the functions are supposed to do
>> (because it's defined in the same place where is defined what the
>> compiler itself is supposed to do).
>
> Now I completely lost. Are you saying that a C compiler recognizes
> specific function calls like printf and when you write printf("hello
> %s", "world"); it realizes that a puts("hello world"); would be much
> cheaper as part of the optimization?

I'm not talking about C at all; this is a discussion of the merits of
features built into the compiler versus features in a standard library.
I talk about C when discussing Sergio's examples in C, and I talk about
other languages to bring in examples. This discussion is in principle
not specific to any language (other than maybe XSCB, given Sergio's
experience with it :).

But of course a C compiler may recognize a function "printf" and
possibly do such an optimization. IIRC I've heard about C
"preprocessors" that do exactly this: go through your code, analyze all
printf statements and replace them with their idea of what's an optimal
implementation.


> Or you are talking about intrinsic functions within the library ...

We seem to need a definition of "intrinsic function". It seems that
already what Sergio, Olin and I think of when we use this term doesn't
match, and you now added to the mix intrinsic functions in the library
:)

> ... where it still uses the printf function but makes all the code
> optimizations as the library function was written in the place where
> it was called from?

If by "in the place" you mean by the same vendor, then yes, this is a
possibility.


> That's because of the operator '+' can be overloaded in a string type
> object. In laguages like Pascal the string has a different structure
> than in the ANSI C, so you have the actual length of the string at
> the very beginning of the string  buffer (it is like a minimalistic
> buffer header). That makes it possible to implement string
> manipulations faster and easier -- therefore a string concatenation
> is an easy task by language definition.

Here you're comparing two different string implementations. That's a
different issue; this here is all about built-in vs library. The
question whether Pascal-type strings are more efficient than C-type
strings has nothing to do with this.


{Quote hidden}

Haven't done much Unicode coding lately? :)  It's not so easy. Unicode
is /not/ just 16-bit wide characters. The arguably most common Unicode
encoding is UTF-8, which has its characters in 8, 16 and 32 bits,
depending on the character. Then there are other flavors, most with
varying character widths. So just treating each character as a 16-bit
entity doesn't work.


> Also I am not sure with HiTech but in many embedded C compiler you can
> tell which type of printf do you want to use within your application
> (there are some minimalistic version, with some restricted version
> like no float types and the full version). Hang on a minute, are you
> saying the HiTech automatically chooses the smallest/fastest but
> still functional one when you are compiling your application?

Yes. Independently of what exactly HiTech does here (I don't have any of
their PRO compilers), one can go rather far with that and actually, in a
fine-grained way, automatically customize the printf source to really
only include the parts that are actually needed. (As long as you're
thinking of a C library, this could be done by preprocessor macros that
the compiler gathers while analyzing the application and the passes to
the printf source when it compiles it.)

Gerhard

2009\07\15@084611 by Russell McMahon

face picon face
>> Are you saying that a C compiler could understand that "sin()" is
>> standard and generate straight math processor instructions (intel FP
>> has had a FSIN instruction since forever) rather than a library call?

We are the Borg of Pentium.
Division is futile.
You will be approximated!


              Russell McMahon

2009\07\15@090208 by sergio masci

flavicon
face


On Wed, 15 Jul 2009, Gerhard Fiedler wrote:

> I'm not talking about C at all; this is a discussion of the merits of
> features built into the compiler versus features in a standard library.
> I talk about C when discussing Sergio's examples in C, and I talk about
> other languages to bring in examples. This discussion is in principle
> not specific to any language (other than maybe XSCB, given Sergio's
> experience with it :).
>

XCSB

XCASM

XCPROD

:-)


Friendly Regards
Sergio Masci

2009\07\15@092212 by Gerhard Fiedler

picon face
sergio masci wrote:

>> I resisted the temptation to quote all the stuff again... :)
>
> I felt it was necessary because several days have gone by between
> your post and my response.

Yes... no critique meant with my comment. It just was /a lot/ :)


{Quote hidden}

Would you call the C++ standard library functions (like
std::list::insert) "intrinsic functions"? At least the meaning that this
term seems to have in the Microsoft VC++ and gcc compiler documentation
is not what I'm talking about.


{Quote hidden}

Not sure to what degree a compiler "understands", and I don't want to
drift off in a discussion about the arbitrary shortcomings of C or C++.
But when a compiler "knows" the intent of the line (because all
operations that happen are defined in the language standard) and knows
the implementation (because it of course "sees" the implementation of
the operators that are implemented in the compiler, but it also sees the
implementation of the library functions by making their sources
available) -- what's the difference that's left between built-in and
library?


{Quote hidden}

Right. My point was that if 8-bit strings are built-in and Unicode
strings are in a library, and you are claiming (elsewhere) that the
built-in syntax can be different from library syntax, then I need to
make the Unicode string syntax completely different -- structurally
different -- from 8-bit string syntax. Can you imagine that? What a
pain.


{Quote hidden}

Be that as it may, but this is a difference between a specific C-style
syntax and a specific BASIC-style syntax. There's nothing that would
prevent a language to allow BASIC-style syntax for libraries (functions
with several indentifiers that separate the arguments and together form
one library call), so I don't really see the point WRT our discussion of
built-in vs library.

FWIW, my point was about specific function names. You didn't use my
function names, so I don't know what you meant here. If you want to, can
you rewrite this using substr_from_to and substr_from_len, then explain
what is the difference to the BASIC variant?


{Quote hidden}

We probably need a common definition of "intrinsic function". I was
talking about standard libraries that contain functions (and other
language elements) that are defined in the language standard, in the
same way as the language elements that the compiler implements. And
additionally, to give the compiler access to the specific implementation
(not only to the intent), the libraries are available to the compiler in
source code.

The intrinsic functions that are used e.g. in gcc and VC++ are not of
this type. Most (if not all) are not even standard.


>>> I talk about the brick wall between the compiler and the libraries
>>> and you respond with "make the source of the libraries available".
>>
>> No. I say consider that the library is a /standard/ library. Adding
>> the source code is in addition, so that the compiler not only
>> "knows" the intent, but also sees the implementation.
>
> got you. intrinsic + library

I'm not so sure... :)  "Intrinsic" seems to imply (possibly among other
things) that the library is written by the compiler vendor. I don't mean
to imply this.


>> Look at the C++ standard library definition for std::list::insert,
>> for example. It contains a definition that allows each C++ compiler
>> to "understand" what a call to std::list::insert is supposed to do.
>
> I will look at this. Can you point me at a specific doc and library
> so that I can be sure to look at exactly what you are looking at.

Take any standardized language with a standardized library. For example,
the C++ standard (the real one costs money, but here is a not quite up
to date one <http://www.open-std.org/jtc1/sc22/open/n2356/>). And of
course, anything that's missing /could/ be there -- it just isn't.

Or C# (ECMA-336) and the .NET CLI (ECMA-335), even though that's
possibly a bit different.

Gerhard

2009\07\15@093935 by Gerhard Fiedler

picon face
sergio masci wrote:

>> sergio masci wrote:
>>
>>> Having a language and compiler that would generate efficient
>>> multitasking code on both a 628 and Windows XP in a multicore
>>> processor would be a feat. But the hardest part (that of getting it
>>> to work on a 628) is done! Surely you can see that doing the same
>>> for a system with MUCH better resources is trivial in comparison.
>>
>> No, I can't see that. Portable, safe and efficient multitasking on a
>> modern multicore system is in no way trivial. It is IMO more complex
>> than multitasking on a 628, by a few magnitudes.
>
> No Gerhard the fundamental principle is still indentical - you switch
> task contexts. Wheather this means that you need to completely save
> one CPU context and load another OR you arrange for the the task
> contexts to co-exist and simply switch between them is upto the
> implementor.

This is in the context of the compiler implementing multitasking.
Multitasking is not only about starting threads and maintaining their
state, it's also about synchronization between threads, and do so
efficiently. And many aspects of this depend on the exact situation.

One difference between the 628 and Windows XP or Linux is that the
compiler in the first case does part of what the OS it the other case
does, so the implementations are different. The other is that I have a
somewhat more sophisticated expectation of how multitasking works on a
Windows or Linux PC when compared to a 628.

Also, on a single-core system, an entity that can be manipulated
atomically can be used to synchronize between threads. We do this all
the time on PICs with bits and bytes. It doesn't work this simple way on
a multi-core system; you need additional provisions to synchronize the
corresponding processor cache lines.

Then there's the performance issue. On a single-core system, normal
locks for accessing containers and making sure they are always in a
consistent state are good enough; as long as the code is inside the
container, it's doing useful work, so serializing even read accesses
isn't going to cost me much if anything. However, on a multi-core
system, reader/writer locks may make a lot of sense and speed things up
quite dramatically, as now several readers can read literally /at the
same time/ the container, and the lock is only used to make sure a
writer is always alone in the container.

So there are quite substantial differences in multitasking between a
small bare-metal system and a bigger system with a complete OS on one
hand, and between single-core systems and multi-core systems on the
other hand. If a compiler is to implement multitasking, it needs to take
all this into account.

I don't know whether it would make sense to use the same functionality
for multitasking keyboard input, display output and measurement on a 628
and for a web server on Linux, but I suspect it wouldn't.

Gerhard

2009\07\15@094600 by Gerhard Fiedler

picon face
William "Chops" Westfield wrote:

>> If I had meant intrinsics, I'd havewritten about intrinsics.
>
>> I said that if a library is a /standard/ library (and I have  
>> mentioned this word "standard" a few times; you didn't seem to pick  
>> up on this),
>
> What exactly do you see as the difference between an "intrinsic"  
> function and a Standard library function?  I mean sin() is a standard  
> library function in C, but an intrinsic function in fortran/pascal/
> etc, right?

My point in this whole thing is exactly that there isn't a big
difference, and I'm trying to get to the bottom of what Sergio thinks is
the difference.

So this would be a question for Sergio :)

> Are you saying that a C compiler could understand that "sin()" is
> standard and generate straight math processor instructions (intel FP
> has had a FSIN instruction since forever) rather than a library call?
> (assuming that it "knows" that the instructions and the library are
> supposed to generate the same results...)

Sergio's example a while ago was that since the compiler knows what
remove(), insert() and replace() do (because they are part of the
language rather than a library), it is possible for the compiler to
replace a sequence of remove() and insert() with an appropriate
replace(), making the code more efficient.

My counter-argument was that if remove(), insert() and replace() are
/standard/ functions, the compiler doesn't have to actually implement
them to know that it can replace a remove() call followed by an insert()
call with a replace() call -- they may just as well be in a (standard!)
library.

(All obviously used in a way that this is actually correct and makes
sens. We're not talking about compiler mistakes or library bugs or
unusable definitions... :)

Gerhard

2009\07\15@100107 by Gerhard Fiedler

picon face
sergio masci wrote:

> From what you are saying now, it is clear to me that yes you are
> talking about intrinsic functions.

What follows doesn't seem to match my understanding of "intrinsic
function". As long as we use this term, can we define it, so that we
have a common understanding?

> Yes the function is defined in a library but the compiler also knows
> about the intent of the function.

Correct, but maybe better "the source code of the function is defined in
a library". The intent of the function is defined in the language
standard.

(Being defined in a library doesn't seem to match what's generally meant
with "intrinsic".)

> The intent is seperate from the definition since and is included by
> the compiler writer directly into the compiler.

Correct.

> The definition of the function is provided by someone else (library
> implementor?) ...

Correct. Not necessary, but may be.

> ... and may even be at odds with what the compiler understands it to
> be.

It is possible, of course, that they are at odds, but I'd classify this
as a bug (in the compiler, in the library or in the standard).

It seems we're getting somewhere :)  See also my response to Bill.

Gerhard

2009\07\15@100309 by Dario Greggio

face picon face
Gerhard Fiedler ha scritto:

> Sergio's example a while ago was that since the compiler knows what
> remove(), insert() and replace() do (because they are part of the
> language rather than a library), it is possible for the compiler to
> replace a sequence of remove() and insert() with an appropriate
> replace(), making the code more efficient.

Just my .0002c :) into this interesting topic:

won't this make the programmer "lazier", while OTOH C lets you use your
brain better?

2009\07\15@103003 by Russell McMahon

face picon face
Note that you're no worse off if it doesn't support the character
representation you like.  The reverse can also be a pain, like Java where
everything is one of those unicode thingies.  Maybe that's nice if you want
to appease some illiterate in a distance jungle somewhere, but it's a hassle
if you want to send a stream of 8 bit characters to a microcontroller.  And
now even 65K glyphs are apparently not enough.  Is this nonsense ever going
to end?

Only peripherally related to the main point of this thread but:

I know (hope?) that that comment was included for its provocative value
rather than being intended asa racist / jest plain iggerant comment. To
characterise those whose languages require, for whatever reason, more than 8
binary bits to represent them as
- illiterate
- far away (and thus by implication unimportant)
- jungle (savage/ unworthy ...)

is rather closer to ad hominem attacj than useful comment. I'm not overly
into PC stuff (nothing to do with IBM)(& despite impressions formed to the
contrary by some :-)) BUT you risk rejecting an awful lot of people and
knowledge and usefulness and more if you genuinely suggest sticking to 8
bits because the mother tongue jest happens to manage OK with that many, or
even less. (If you can't express it in Baudot it's not worth saying? :-)
)(Or Ogham). Sure, needing to use extra bits to accomodate material that you
have no interest in is a pain, but largely not a major problem with modern
systems * except in systems so small that they can probably afford to not
deal with such codes. (* Nobody should ever need more trhan 640 kB of
memory**).


   Russell

** Claims to the contrary notwithstanding, Gates denies ever having said it.









2009/7/15 Olin Lathrop <@spam@olin_piclistKILLspamspamembedinc.com>

{Quote hidden}

> -

2009\07\15@103135 by Russell McMahon

face picon face
Sorry ... meant to trim.
Not used to using GMail for lists.
Hides the quotes where you can't see them (easily).


         Russell

2009\07\15@120514 by olin piclist

face picon face
Gerhard Fiedler wrote:
> Right. My point was that if 8-bit strings are built-in and Unicode
> strings are in a library, and you are claiming (elsewhere) that the
> built-in syntax can be different from library syntax, then I need to
> make the Unicode string syntax completely different -- structurally
> different -- from 8-bit string syntax. Can you imagine that? What a
> pain.

Maybe not.  If each type of string is a different data type, then the syntax
can be simple and the compiler could even convert from one representation to
another if this can be done unambiguously.

For example, let's say the string concatenation operator is "+":

 strc <-- stra + strb

could work as long as all three are some type of string data type.  If the
representations are well enough defined, it should be possible to define
rules of how one representation is converted to another, and to produce a
compile time error when this could not be done.  With consitent promotion
rules, you can use what looks like the same string constant in different
circumstances.  For example:

 stra is ascii_string_t
 stru is unicode_string_t

 stru <-- stru + stra + " blah"

Let's say UNICODE_STRING_T is a superset of the string type ASCII_STRING_T.
In that case STRA would be promoted to unicode before being appended to
STRU.  The string constant " blah" could either be defined as ASCII_STRING_T
and thereby automatically promoted when needed, or possibly the compiler can
tell from context which data type is needed.

The point is that it is certainly possible to handle various string
representations built into a compiler without operator or syntax bloat.
Converting between the various representations could actually be quite
useful.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\15@132552 by sergio masci

flavicon
face


On Wed, 15 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

No.

{Quote hidden}

home in on "'knows' the intent of the line"

I am not talking about parsing a line and understanding it its meaning,
I'm talking about understaning several lines as a unit. What is the
programmer trying to say in these several lines.

If I write:

       for (j=0; j<strlen(str); j++)
       {
               if (str[j] >= 'a'  &&  str[j] <= 'z')
               {
                       str[j] = str[j] ^ ('a' ^ 'A');
               }
       }

would you expect the compiler to flag "j<strlen(str)" or maybe replace it
with the much more optimised:

       xlen = strlen(str);

       for (j=0; j<xlen; j++)
       {
               if (str[j] >= 'a'  &&  str[j] <= 'z')
               {
                       str[j] = str[j] ^ ('a' ^ 'A');
               }
       }

maybe optimise it further as:

       xlen = strlen(str);

       for (j=0; j<xlen; j++)
       {
               ptr = &str[j];

               if (*ptr >= 'a'  &&  *ptr <= 'z')
               {
                       *ptr = *ptr ^ ('a' ^ 'A');
               }
       }

So here the compiler looked at several statements as a single unit and was
able to optimise it (this is quite within the capabilities or modern C
compilers).

Now going a little further you could say that it was the intent of the
programmer to "change all lower case alpha characters to uppercase". So
the intent of the programmer spans several statements.

Put this another way, if I write in assembler:

       movf        X+0, w
       addwf        Y+0
       btfsc        STATUS, C
       incf        Y+1
       movf        X+1, w
       addwf        Y+1

This code adds one 16 bit variable to another 16 bit variable. Here the
programmers intent is to add 16 bit variable X to 16 bit variable Y.

It is far easier for you, me and the compiler to understand the
programmers intent if instead I write:

       X = X + Y;

{Quote hidden}

Yes you are right it would be a pain. But it is a move in the right
direction.

{Quote hidden}

I think I understand what you mean. But just to clarify: You are
suggesting that instead of simply defining a function as:

       substr(char *, int);
       substr(char *, int, int);

That I could instead write:

       substr(char * 'FROM' int);
       substr(char * 'FROM' int 'TO' int);
       substr(char * 'FROM' int 'LENGTH' int);

Interesting.

But you'd still need to be able to attach a boat load of attributes to the
function to give the compiler the same capabilities it would have if these
functions were actually built-in language constructs and the compile times
would be horrendous.

I think it would be do-able but you'd still need some kind of meta
language to describe how these functions would interact with each other,
their parameters and local variables that are used with them (from outside
the call and not just as a parameter).

>
> FWIW, my point was about specific function names. You didn't use my
> function names, so I don't know what you meant here. If you want to, can
> you rewrite this using substr_from_to and substr_from_len, then explain
> what is the difference to the BASIC variant?
>
       for (j=0; j<len; j++)
       {
               len2 = strlen(arr[j]);

               arr2[j] = substr_from_len(arr[j], 0, len-2);
       }

can you see that "len-2" should actually "len2"?

{Quote hidden}

An intrinsic function is one that the compiler understands intimately. Not
just what parameters it takes and what result it returns. A good example
of an intrinsic function is the add operator ('+'). It seems to be used
differently to a user defined function because you use it in expressions
as an infix operator

e.g.
       A = B + C

       funcX(B + C)

But this is just for convenience. If you were able to define a symbol in
C, say 'ADD', with all the attributes that the '+' symbol has then '+' and
'ADD' would both behave the same way and the compiler would generate the
same optimised code for both.

e.g.
       A = B ADD C

       funcX(B ADD C)

In C++ you can actually write your own add ('+') operator function.

{Quote hidden}

No not necessarily. If the compiler vendor were explicit as to how an
intrinsic function's counterpart in the library should be written then a
third party could do the work. But it does seem like a lot of trouble to
go to on the part of the compiler writer.

{Quote hidden}

Ok I've had a look on the net and it's just template stuff. As I've said
before, the compiler isn't really understanding intent here it's just
mechanically churning out code and reducing it as much as possible. It
gives the illusion that it understands what is going on because so much
source code is being condensed into a small executable but the reallity is
that all that source code is hand holding the compiler and telling it
exactly what to generate.

Friendly Regards
Sergio Masci

2009\07\15@155706 by sergio masci

flavicon
face


On Wed, 15 Jul 2009, Dario Greggio wrote:

{Quote hidden}

You could say the same about moving from C to assembler.

But as I keep saying, the main point isn't about optimisation it's about
understaning the intent of the programmer. The better you understand the
intent the better you can catch mistakes. It just so happens that the
better you understand the intent the better you can ALSO optimise the
generated code.

Friendly Regards
Sergio Masci

2009\07\15@230619 by Gerhard Fiedler

picon face
sergio masci wrote:

>> (other than maybe XSCB, given Sergio's experience with it :).
>
> XCSB
>
> XCASM
>
> XCPROD

I had already remembered that it starts with X and contains the letters
B, C, S and X. Then I could remember that it ends with B.

Now I hopefully will remember that it starts with XC -- and will never
again spell it wrong :)

Greetings to the left side of your desk :)

Gerhard

2009\07\16@080501 by Gerhard Fiedler

picon face
sergio masci wrote:

>>> It is now clear to me that you are talking about intrinsic
>>> functions. Yes the function is defined in a /standard/ library but
>>> the compiler also knows about the function independently of the
>>> library.
>>
>> Would you call the C++ standard library functions (like
>> std::list::insert) "intrinsic functions"? At least the meaning that
>> this term seems to have in the Microsoft VC++ and gcc compiler
>> documentation is not what I'm talking about.
>
> No.

But this is what I'm talking about. So I was right with my suspicion
that I wasn't talking about what you called "intrinsics".


> home in on "'knows' the intent of the line"

This is what I'm trying to do. This is the reason why I want to
understand what it is that makes a function that is defined by the
standard (and is implemented in a library) different from a construct
that is defined in the same standard and implemented inside the
compiler. I haven't yet seen an example by you that I could understand
-- and that wasn't about something else.


[Snipped string loop optimization example.]

> So here the compiler looked at several statements as a single unit and
> was able to optimise it (this is quite within the capabilities or
> modern C compilers).

Or other languages... something like this seems to be standard in good
compilers.


> It is far easier for you, me and the compiler to understand the
> programmers intent if instead I write:
>
>        X = X + Y;

Agreed.


>> Right. My point was that if 8-bit strings are built-in and Unicode
>> strings are in a library, and you are claiming (elsewhere) that the
>> built-in syntax can be different from library syntax, then I need to
>> make the Unicode string syntax completely different -- structurally
>> different -- from 8-bit string syntax. Can you imagine that? What a
>> pain.
>
> Yes you are right it would be a pain. But it is a move in the right
> direction.

I'm not sure. I think I wouldn't like it. For example, it seems that for
some things Pascal-style strings are more efficient than C-style
strings. There's nothing that prevents me from working with Pascal-style
strings efficiently in C++ (and no matter whether ASCII, 8-bit with
different codepages, different encodings of Unicode) -- in the same
idiom that is used for standard strings in C++. This is because strings
are /not/ built into the language (among other things).

Being able to work with similar types in a similar way is important for
code quality. If you need to use a different idiom for different string
encodings, code quality goes down -- and code quality is important.


{Quote hidden}

That's one possible form, but it's not quite what I meant. What I meant
is that you have a way to declare the function and syntax so that you
actually can write

  SUBSTR str1 FROM pos1 TO end

and the compiler knows what library to call in which way. This doesn't
look too complicated, and it's not actually that different from

  SUBSTR_FROM_TO str1, pos1, end

Just a slightly different syntax.

> But you'd still need to be able to attach a boat load of attributes to
> the function to give the compiler the same capabilities it would have
> if these functions were actually built-in language constructs and the
> compile times would be horrendous.

I don't understand why. This doesn't seem to be much more complicated to
parse than a normal function call. It's a starting token SUBSTR,
followed by five tokens that have to be three expressions interspersed
with FROM and TO.

> I think it would be do-able but you'd still need some kind of meta
> language to describe how these functions would interact with each
> other, their parameters and local variables that are used with them
> (from outside the call and not just as a parameter).

I'm not sure what you mean by "interaction". The interaction of
functions is defined by the language standard that defines what they do.
Their arguments would be described just as they are in any procedural
language. You'd need a bit of a meta language to define such a
construct, but not much I think. I don't think this goes much further
than a normal function declaration; just add to the "<typename>
<identifier>" pairs a possible pair "KEYWORD <identifier>".


> An intrinsic function is one that the compiler understands intimately.
> Not just what parameters it takes and what result it returns.

Next step is to define what "understands intimately" means. Does a
specification (like in a language standard) qualify?

> In C++ you can actually write your own add ('+') operator function.

Which would be different from the standard operator+() functions, in
that the compiler doesn't "know" what they are supposed to be doing and
has to treat them as normal function calls (in the case of C++ with the
special rules that the language standard defines for operator+(), of
course).


{Quote hidden}

Not sure whether the standard can tell you what kind of optimizations
actual compilers implement. Much of this is probably a trade secret.
Then I'm not convinced a casual look at this is enough to find out what
/could/ be implemented. They don't talk about optimizations in the
standard; they just say what has to be the result.

Going back to one of your original arguments, the one that prompted my
question about what the difference is between list operations that are
implemented by the compiler and list operations that are implemented in
a standard library: the substitution of a delete from a list followed by
an insert into a list at the same location by a replace.

If you want to implement such an optimization in your compiler, what's
the difference between having these functions as part of the compiler,
or having them defined as standard library functions in the standard
that the compiler is based upon? In both cases, the compiler "knows"
that this substitution is possible and the exact implementation of the
three functions is not necessary to be known for this optimization to be
possible.

Gerhard

2009\07\16@083000 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

> It really has been confusing trying to figure out what exactly your
> point is.

Sergio's point is that there is a really important difference WRT
optimizations between constructs that are implemented in the compiler
and constructs that are implemented in a standard library (that is
defined in the same language standard). My point is that I don't see a
difference.

His example with respect to this was that in the case that the compiler
implements list handling, it is able to "know" that a 'delete' followed
by an 'insert' into the same location can be replaced by a 'replace' as
optimization. He talks about 'intent', and that the list handling being
implemented by the compiler allows it to better grasp the programmers
intent.

My point is that if the list handling functions 'delete', 'insert' and
'replace' are defined in the language standard that the compiler
implements, it is able to detect that intent in the same way and make
this optimization, no matter whether the functions themselves are
implemented in the compiler or in a (standard) library. The important
thing here is that they are defined by the language standard.

Most of the rest of the thread goes back to this; this is fundamental to
keep in mind as the issue.


>> Not quite. Firstly, I was talking about /standard/ libraries, where
>> the compiler also "knows" what the functions are supposed to do
>> (because it's defined in the same place where is defined what the
>> compiler itself is supposed to do).
>
> But that's exactly what intrinsic functions are, which you strongly
> claimed you weren't talking about when I suggested that's what you
> might mean.  Now I am (and I think Sergio too) really confused.  How
> is what you mean not intrinsic functions?

For example, in C++ there is are list handling function defined in the
standard (e.g. std::list::insert). This is what I mean, this is what I
wrote. I have never heard anybody refer to this as "intrinsic function".
The intrinsic functions that are called so by Microsoft (in VC++) and
the writers of gcc are typically /not/ part of the language standard,
and therefore something completely different from what I'm talking
about.


> Note that you're no worse off if it doesn't support the character
> representation you like.  

Yes, I am -- if the string library doesn't use the same syntax that the
built-in strings use. Consistency is important for code quality, and
having to use different code constructs and functions for doing the same
things with different types of strings lowers consistency and therefore
code quality. For example, you may be able to use "string1 + string2"
for concatenating ASCII strings, but have to use concat(string1,string2)
for Unicode strings or 8-bit strings that handle codepage translations.
I have to repeat myself: what a pain.

> The reverse can also be a pain, like Java where everything is one of
> those unicode thingies.  

Exactly. For flexibility, it is important to be able to choose -- which
speaks against being built-in. (Not necessarily, but as a tendency.)

> Maybe that's nice if you want to appease some illiterate in a distance
> jungle somewhere,

Now this is a completely unnecessary and stupid remark. What has using a
character set that can't be represented in ASCII to do with illiteracy
or distant jungles?


> So it sounds like you want a bunch of intrinsic functions (which
> represent a large amount of compiler work), but have any optimization
> defeated and your own function called if you define one?

I don't "want" any of this. You need to understand the context of this
argument, and place what I write into this context. No affirmation here
stands alone.

But yes, this would be (and is) typically possible with standard
functions that are implemented in a library. No amount of optimization
in the compiler is guaranteed to address all cases, so being able to use
a custom implementation is possibly one of the reasons of the popularity
of C in the small micro market.


{Quote hidden}

Can you make up an example here? I think it's the other way round: if
it's built into the language, there tends to be a special syntax,
whereas if it's part of a standard library, it tends to use the standard
syntax that's already there.

Gerhard

2009\07\16@084216 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

>> Right. My point was that if 8-bit strings are built-in and Unicode
>> strings are in a library, and you are claiming (elsewhere) that the
>> built-in syntax can be different from library syntax, then I need to
>> make the Unicode string syntax completely different -- structurally
>> different -- from 8-bit string syntax. Can you imagine that? What a
>> pain.
>
> Maybe not.  If each type of string is a different data type, then the
> syntax can be simple and the compiler could even convert from one
> representation to another if this can be done unambiguously.

Correct. But this was in the context of the various claims that there is
an essential difference between built into the compiler and in a
library. Both you and Sergio said at one point that the syntax could be
different for the constructs built into the compiler than what's
possible for features implemented in a (standard) library. Here you're
saying that the syntax can be the same.

I'm with you on this... (FWIW, what you describe is how strings are
implemented in C++.) But then you need to make sure that the syntax for
the constructs built into the compiler is not different from the syntax
that's possible for constructs in a (user) library. Can't have it both
ways.

Gerhard

2009\07\16@090721 by olin piclist

face picon face
Gerhard Fiedler wrote:
>> I think part of the point is that certain features, like the string
>> handling Sergio described, require a lot less special syntax when
>> built in than they would require special functions if "built in" that
>> way.
>
> Can you make up an example here? I think it's the other way round: if
> it's built into the language, there tends to be a special syntax,
> whereas if it's part of a standard library, it tends to use the
> standard syntax that's already there.

I did provide some examples that you snipped.  Using, for example, the "+"
operator for string concatenation is no additional syntax at all.  It can
also handle various cases of strings of different types (ASCII, unicode,
whatever) or whether they are characters or strings if the language makes
such a distinction.  Unless you allow for function overloading, you'd have a
large mess of function names for all the possible combinations.  Even
without overloading you probably have a few for different special cases for
efficiency.

Using the operator in this example, it is easier for the compiler to "see"
what is going on and deal with the combinations of string types and special
cases itself.  You could in theory define a generalized string concatenation
function that the compiler understands as a special case, but that's really
the same thing with a different syntax, more work for the compiler writer,
and less readable code.

I'd rather write

 strb <-- stra + stru + " more stuff"

than

 strb <-- StringConcatenate(stra, stru, " more stuff");

and I think Sergio is saying that from a compiler writer's point of view
he'd prefer the first also.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\16@165657 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

{Quote hidden}

So do I, but I fail to understand why this requires that the string
handling is built into the compiler.

Your preferred syntax looks (in principle) quite similar to the C++
std::string syntax, where normal string handling is implemented in a
standard library.

Gerhard

2009\07\16@172509 by olin piclist

face picon face
Gerhard Fiedler wrote:
>> I'd rather write
>>
>>   strb <-- stra + stru + " more stuff"
>>
>> than
>>
>>   strb <-- StringConcatenate(stra, stru, " more stuff");
>
> So do I, but I fail to understand why this requires that the string
> handling is built into the compiler.
>
> Your preferred syntax looks (in principle) quite similar to the C++
> std::string syntax, where normal string handling is implemented in a
> standard library.

First, that only works when a language allows user defined operators like
C++ does, but most other compiled languages don't.  Even then, the compiler
only knows that some library routine has to be called to perform whatever
the operation is.  It doesn't know it's string concatenation and therefore
doesn't know as much about the intent of the statement as it would if it was
built in.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\16@173435 by sergio masci

flavicon
face


On Thu, 16 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

*** YOU *** are saying "'knows' the intent of the line".
*** I ***   am saying"'knows' the intent of several seperate lines as one
unit"

You are happy to see:

       X = X + 0;

reduced to NOTHING (not a critisim). You have an expectation of this
because the compiler understands the intent of the line.

I am saying something like:

       j = x * 2 + y * 2;

       temp = arr[j];

       j = (x + y) * 2;

       arr[j] = temp;

should also be reduced to nothing *** AND *** the compiler should warn the
user that this piece of code has no effect and so may be in error. This is
not possible if you understand only the intent of single lines but can be
fudged by the compiler by keeping track of what is evaluated and where the
result is placed. So although the compiler might be able to reduce it to
zero it doesn't understand that this might be an error.

Things get much more difficult if we re-write the above as:

       int func_get(int arr[], int x, int y)
       {
               int        j;

               j = x * 2 + y * 2;

               return arr[j];
       }

       void func_set(int arr[], int x, int y, int val)
       {
               k = (x + y) * 2;

               arr[k] = val;
       }

       temp = func_get(arr, x, y);

       func_set(arr, x, y, temp);

Ok the compiler *** MIGHT *** still be able to hack this if it is very
smart and all the source is available for the functions. BUT change the
type of the array from a straight forward int to a struct and things get
incredibly complicated (I mean they are really complicated now with int
but they will get MUCH worse with a struct :)

Here having built-in type like STRING, LIST etc reduces the complication
because the lanuage and compiler control the way they are used. It's like
the difference between a menu interface and a command line interface. With
the menu interface you guide the users interactions and there can be no
unexpected commands issued that will break things (kind of).

{Quote hidden}

But the same argument could be made for floating point. Many people
require different precission (wheather greater or less than that provided
by C) yet they either use what is available in a way that suits them of
they use a specialised library *** AS WELL *** as the supported floating
point.

Often people will fit the solution to the tools available.

{Quote hidden}

It's not the parsing that's the problem. The problem is providing
information to the compiler about the way these functions interact. I'm
not talking about the calling protocol (the way parameters are evaluated
and pased on the stack or the result is returned) I'm talking about how
functions relate to each other over several lines of code.

Consider this:

       void process_substr(char *str, int pos1, int pos2)
       {
               char        *tmp_str;
               int        len;

               len = pos2 - pos1;

               tmp_str = malloc(len + 1);

               strncpy(tmp_str, (str + pos1), len);

               ...
               ...
               ...

               free(tmp_str);
       }

Now turn this into a real example:

       char * string_alloc(int len)
       {
               char        *tmp_str;
               tmp_str = malloc(len + 1);

               return tmp_str;
       }

       void string_assign(char *dst_str, char *src_str)
       {
               strcpy(dst_str, src_str);
       }

       char * string_substr(char *str, int pos1, int pos2)
       {
       static        char        *own_str;
               int        len;

               len = pos2 - pos1;

               strncpy(own_str, (str + pos1), len);

               return own_str;
       }

       void string_release(char *str)
       {
               free(str);
       }

       void process_substr(char *str, int pos1, int pos2)
       {
               char        *tmp_str;
               int        len;

               len = pos2 - pos1;

               tmp_str = string_alloc(len + 1);

               string_assign(tmp_str, string_substr(str, (str + pos1), len);

               ...
               ...
               ...

               string_release(tmp_str);
       }

in the above, how would I tell the compiler the relationship between
string_alloc, string_assign, string_substr and string_release such that  
the compiler is able to:

(1) ... indicate an error if tmp_str is not initialised with string_alloc
before string_assign is used on it (simply assigning a value to tmp_str is
not what I mean, I mean actually using string_alloc to initialise it).

(2) ... indicate an error if tmp_str goes out of scope before it is
cleaned up with string_release

(3) ... optimise the combined use of string_assign and string_substr

(4) ... recognise that tmp_str is undefined after the use of
string_release

This is why you need to be able to add special attributes to the
functions, to be able to tell the compiler about all this stuff.

And yes I know about C++ (I've been using it for many years) but creating
a boat load of classes to *** TRY *** to do the same thing is not the
same.

{Quote hidden}

One of the reasons we have a simplified common protocol that allows any
function to be called from anywhere in the program is to eliminated the
complexity that would otherwise come about by trying to juggle the actual
prameters used in-line (where the function is called) with the formal
parameters (how the parameters are defined within the function).

Consider this

       int func_A(float x)
       {
       ...
       }

       int        val_1;

       unsigned char
               val_2;

       float        val_3;


       func_A(val_1);

       func_A(val_2);

       func_A(val_3);

in each of these cases C ensures that the actual paraemeters val_1, val_2
and val_3 are floats before passing them to func_A. If they are not
already floats, it promotes them. Furthermore actual the parameter (val_1,
val_2 and val_3) is copied (promoted first if necessary) to a place where
the function expects it to be when it is called. The function does not
operate on val_1, val_2 or val_3 directly. Something similar happens for
the return value. All of this is the calling protocol.

So yes the the compiler "understands" a standard library function in as
much as it "understands" its parameter requirements. Other than ensuring
that actual parameters are promoted to the correct type and copied to the
correct place the compiler does very little else across the function
boundry. Some compilers are much more intelligent than others and try to
see through (or even punch through) the function boundry but there again
there is only so much that the compiler can do because of the complexity
of the function. Regardless it is still very difficult for the compiler to
combine information across the function boundry because the function needs
to stick to the calling protocol if it is to be used elsewhere.

Inline functions reduce the calling protocol burden because it becomes
possible to tailor each instance of the called function to the place where
it is called. Howver there is only so much you can do with this because
these inline functions may themselves call other system functions which
are not inline. AND this doesn't help with the "understanding" of the
relationships between functions (see the string_assign example I gave
above). For this you still need some way of adding specialised attributes
to a function which tell the compiler about these relationships.

C++ templates give the illusion that the compiler really understands
what's going on - it still doesn't. What's happening is that a lot of
stuff gets expanded "inline" (not just functions). So the compiler is able
to do lots of optimisations. For example it might see that an int is being
promoted to a float so that it can be passed to a function (method) which
is then converting it to an int to pass it to another function (method).
The compiler might then simply allow the promoting / converting to cancel
each other and use the original. This looks to the user as if the compiler
understood what is going on. It doesn't. It no more understands than a
calculator does when you press the -/+ key twice to get to the original
value.

The C++ compiler still doesn't understand the relationships between
functions. The programmer does and he arranges all the objects to get
sensible optimised results.

>
> > An intrinsic function is one that the compiler understands intimately.
> > Not just what parameters it takes and what result it returns.
>
> Next step is to define what "understands intimately" means. Does a
> specification (like in a language standard) qualify?
>

No.

{Quote hidden}

Yes I understand what you mean here. But in the case of functions this
relies on the compiler actually recognising the function names and
executing some internal code to perform checks, issue warning (or errors)
and perform optimisations.

That internal compiler code needs to be activated somehow and it needs to
perform a very specific task (not something that would be there anyway -
somthing that is written specially for that one perpose).

If you really wanted to you could say that the function names are
undefined to the compiler but then you need some way of telling the
compiler which functions are special (what their names are) and what is
special about them (under special circustances you can replace func_A +
func_B with func_C). This is why you would need to be able to add special
attributes to a function, so that you can tell the compiler that these are
special functions that need to be handled in a special way (execute the
special internal code for them). (sorry about all the specials :-)

Other than having special attributes you really would need to make these
functions intrinsic (known and understood by the compiler) so that it can
execute its special internal code when it sees them in the users source
code.

Friendly Regards
Sergio Masci

2009\07\18@094923 by Gerhard Fiedler

picon face
sergio masci wrote:

> *** YOU *** are saying "'knows' the intent of the line". *** I ***  
> am saying"'knows' the intent of several seperate lines as one unit"

Ok. But so far you didn't explain how this is different for language
elements that are implemented in the compiler versus language elements
that are implemented in a library. The compiler can only "know" a priori
what a single language element is doing (for both the built-in elements
and the ones that are implemented in a standard library); the rest it
has to figure out based on the program -- independently of where exactly
the language elements are implemented.


{Quote hidden}

How is this dependent on where the involved operators are defined -- as
long as the compilers "knows" what they are supposed to do?

{Quote hidden}

I don't doubt that it's incredibly complicated, but I don't see how the
exact implementation of the various operators affects this optimization.
This optimization is based on the compiler "knowing" that (x * 2 + y *
2) == ((x + y) * 2), no matter how exactly they are calculated. If this
identity can be derived from what's defined in the standard about the
involved operators, then this optimization can be made, no matter where
the operators are implemented. If it's not defined in the standard (for
example, for typical floating point variables, this identity is
generally not given), such an optimization can't be made -- no matter
where the operators are implemented.


> Here having built-in type like STRING, LIST etc reduces the
> complication because the lanuage and compiler control the way they
> are used. It's like the difference between a menu interface and a
> command line interface. With the menu interface you guide the users
> interactions and there can be no unexpected commands issued that will
> break things (kind of).

I still don't see this. You repeat that there is a difference, but don't
really say where the difference is. The analogy with the menu doesn't
seem to be very helpful; if I have a list defined with the operations
insert, delete, replace, find, the "menu" is the same whether they are
implemented in the compiler or in a standard library.

It seems you forget that the library I'm talking about has an interface
that's as strictly and precisely defined as the language itself, by the
same language standard. Can you give an example where a programmer could
give an "unexpected command" in the case the list is implemented in a
standard library, versus the programmer not being able to give that
"unexpected command" in the case it is implemented in the compiler?
(Keep in mind that in both cases it is defined in the language standard
what the programmer can do with the list -- and it's the exact same
definition.)


> But the same argument could be made for floating point. Many people
> require different precission (wheather greater or less than that
> provided by C) yet they either use what is available in a way that
> suits them of they use a specialised library *** AS WELL *** as the
> supported floating point.
>
> Often people will fit the solution to the tools available.

I didn't understand the point you're making here (WRT the discussion
about built-in versus standard library). Yes, I think it's helpful for
both strings and floating-point when a user can use custom libraries
instead of the implementations built into the compiler. And I also think
that this only makes real sense if the syntax is the same in both cases.
And IMO this means that there can't be any syntax advantage for the
implementations that are built into the compiler.


{Quote hidden}

If I understand you correctly, this wouldn't be defined as attribute of
the function, but it would be defined in the language standard, /before/
any implementation of a compiler or a standard library. Every library
function I'm talking about is assumed to be defined in the same language
standard where you define how your built-in list works.


> in each of these cases C ensures that the actual paraemeters val_1,
> val_2 and val_3 are floats before passing them to func_A.

FWIW, I'm not a friend of this. I prefer explicit casts, and if I had a
way to switch off all implicit casts in C or C++, I'd probably do it.
(At least I'd start doing it to see how it works out.) But this is not
related to our discussion about built-in vs library.

> [...] All of this is the calling protocol.
>
> So yes the the compiler "understands" a standard library function in
> as much as it "understands" its parameter requirements.

This is not what I mean. This is what the compiler "knows" about any
function, standard or user-defined. It "knows" more (or could "know"
more) about standard library functions -- as much as there is defined in
the language standard.


> The C++ compiler still doesn't understand the relationships between
> functions. The programmer does and he arranges all the objects to get
> sensible optimised results.

Whether it actual does or doesn't doesn't really matter here. What
matters is whether this is /possible/ -- and whether there's a
difference between implemented in the compiler or in a standard library.

One of your first points was the replacement of a delete followed by an
insert with a replace, for a list. This is possible because the compiler
"knows" what delete, insert and replace do to a list, and how the list
is supposed to work. It needs a definition for this. If this definition
is given in the language standard, I still fail to see how it matters
whether the list is implemented in a standard library or in the compiler
itself.


>>> An intrinsic function is one that the compiler understands
>>> intimately. Not just what parameters it takes and what result it
>>> returns.
>>
>> Next step is to define what "understands intimately" means. Does a
>> specification (like in a language standard) qualify?
>
> No.

I guess we don't really need to define what intrinsic functions are (and
consequently what "understands intimately" means for you), as it's not
what seems to be important in the question what exactly is the
difference in optimizing sequences of commands, depending on whether
they are implemented in the compiler or in a standard library (always
given that both implementations follow the same language standard).


{Quote hidden}

Yes.

> That internal compiler code needs to be activated somehow and it needs
> to perform a very specific task (not something that would be there
> anyway - somthing that is written specially for that one perpose).

Yes. Just as with your insert+delete==replace example. The compiler can
do this, independently of where these functions are implemented.

Pretty much every C++ compiler does this, for example, for custom
implementations of the operator new. This is a special operator, and no
matter whether I use a built-in version or a standard library version
that came with the compiler or my own custom version, there are a number
of special checks that are related to this operator that are executed by
the compiler, based on what the language standard says about operator
new.

This internal code is activated by the use of an operator new; this is a
reserved word, just like all other tokens/identifiers in the language
standard.

> If you really wanted to you could say that the function names are
> undefined to the compiler but then you need some way of telling the
> compiler which functions are special (what their names are) and what
> is special about them (under special circustances you can replace
> func_A + func_B with func_C).

No, I don't want to. The function names are defined in the language
standard, just as the language elements are defined in the (same)
language standard. For example, the C++ std::list::insert. In C++, this
/is/ a special function, and it always has this name. There's nothing
that prevents a C++ compiler from implementing some optimization that is
based on what the standard says this function is doing. There's also
nothing that would prevent a compiler writer from providing an
implementation of this function that is built into the compiler itself.
But it still couldn't do anything with this function that's contrary to
the standard. (If there's something lacking in the standard to make its
definitions more useful, it should be added to the standard -- not to a
single implementation.)

> This is why you would need to be able to add special attributes to a
> function, so that you can tell the compiler that these are special
> functions that need to be handled in a special way (execute the
> special internal code for them). (sorry about all the specials :-)

No. I'm talking /exclusively/ about /standard/ libraries, which contain
implementations for functions that have their behavior defined in the
language standard. Like the C++ std::list member functions, for example.
Their names are known to the compiler implementers; no special
attributes are needed to identify these functions.

> Other than having special attributes you really would need to make
> these functions intrinsic (known and understood by the compiler) so
> that it can execute its special internal code when it sees them in
> the users source code.

No. If their interface is defined accordingly, the compiler can assume
that insert followed by delete can be replaced by replace in a given
situation. The functions must be defined in a way in the language
standard that the compiler can assume this -- but this must be the case
no matter whether the list is implemented in the compiler or in a
standard library. This optimization can then be performed, independently
of whether the functions are implemented by the compiler or in a
standard library. (The compiler's optimization stage that deals with
this type of high-level optimization doesn't even have to "know" this.)

Gerhard

2009\07\18@095930 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

> Gerhard Fiedler wrote:
>>> I'd rather write
>>>
>>>   strb <-- stra + stru + " more stuff"
>>>
>>> than
>>>
>>>   strb <-- StringConcatenate(stra, stru, " more stuff");
>>
>> So do I, but I fail to understand why this requires that the string
>> handling is built into the compiler.
>>
>> Your preferred syntax looks (in principle) quite similar to the C++
>> std::string syntax, where normal string handling is implemented in a
>> standard library.
>
> First, that only works when a language allows user defined operators
> like C++ does, but most other compiled languages don't.  

We're not talking here about specific features of specific languages,
but about what's exactly the difference of e.g. a string implementation
being built into the compiler or implemented in a standard library --
focus on /standard/ library (which means that the string behavior is in
both cases defined by the same language standard).

(In any case, allowing user-defined operators has a tremendous advantage
-- no matter whether the original operator is implemented by the
compiler or by a standard library. But this is somewhat besides the
point here.)

> Even then, the compiler only knows that some library routine has to be
> called to perform whatever the operation is.  It doesn't know it's
> string concatenation and therefore doesn't know as much about the
> intent of the statement as it would if it was built in.

Yes, it does. In C++, for example, the commonly used string
implementation is std::string. I can define my own std::string class
(using Pascal-style strings, for example), and the compiler can (and
should) assume that whatever is defined in the standard is true. If the
standard defines the operator '+' to be concatenation, this is what it
is -- built-in, compiler-vendor-supplied library, or custom
implementation.

The key here is "/standard/ library", as in "library with an interface
that's defined in the language standard, just like all the other
language elements".

Gerhard

2009\07\21@063455 by sergio masci

flavicon
face

On Sat, 18 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

If I understand you correctly what you are saying is that if the compiler
writer is already aware of the /standard/ library before he starts writing
the compiler AND the /standard/ library definition is set in concrete just
as the language definition is then the compiler writer is able to use
intimate knowledge of the /standard/ library functions within the compiler
without incorporating the code generation of the /standard/ library
functions within the compiler but instead leaving this implemented
external to the compiler proper (so that these functions can be written by
someone else and code generated at compile time).

Please confirm this.

Friendly Regards
Sergio Masci

2009\07\21@165303 by Gerhard Fiedler

picon face
sergio masci wrote:

> If I understand you correctly what you are saying is that if the
> compiler writer is already aware of the /standard/ library before he
> starts writing the compiler AND the /standard/ library definition is
> set in concrete just as the language definition is then the compiler
> writer is able to use intimate knowledge of the /standard/ library
> functions within the compiler without incorporating the code
> generation of the /standard/ library functions within the compiler
> but instead leaving this implemented external to the compiler proper
> (so that these functions can be written by someone else and code
> generated at compile time).

Correct.

I thought this all is basically understood when talking about standard
libraries (that is, libraries with an interface that is part of the
language standard).

Gerhard

2009\07\21@172859 by olin piclist

face picon face
Gerhard Fiedler wrote:
> I thought this all is basically understood when talking about standard
> libraries (that is, libraries with an interface that is part of the
> language standard).

Normally "standard library" refers to a documented set of subroutines that
have a widely agreed upon interface and are supplied with the compiler.
This does not mean the compiler understands these interfaces.  That's what
intrinsic functions are.

You seem to want intrinsic functions that you can also write yourself if you
want to.  While that is theoretically possible, it's a lot of work in the
compiler, and letting you provide your own version would defeat some of the
possible optimizations gained by making them intrinsic functions.  That also
means you would have to tell the compiler somehow when you want to supply
your own version of a intrinsic function because it would be too late to
discover this in the linker.  The compiler needs to know, for example, to
avoid replacing the call with inline code it creates itself, as is common
with real intrinsic functions.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\22@071017 by sergio masci

flavicon
face


On Tue, 21 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

Ok so I'm starting to get on the same page as you (I may not agree but at
least I now understand how you are seeing things :)

Furthermore you seem to be saying that using a function call syntax rather
than a verbose statement syntax (e.g. SQL) should be equally easy for the
compiler to understand
e.g.
       A compiler should be able to interpret the following three
       statemets as identical

(1)...        // function call syntax
       if( lt(x, 0), assign(y, 0), assign(y, x) )

(2)...        // C syntax
       if (x<0)
       {        y = 0;
       }
       else
       {        y = x;
       }


(3)...        // verbose syntax
       if x < 0 then
               y = 0
       else
               y = x
       endif

AND because the compiler should be able to "understand" functions as
easily as other language statements that it is a convenient way to extend
the language.

Could you please confirm this.

Friendly Regards
Sergio Masci

2009\07\22@145420 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

> Gerhard Fiedler wrote:
>> I thought this all is basically understood when talking about
>> standard libraries (that is, libraries with an interface that is
>> part of the language standard).
>
> Normally "standard library" refers to a documented set of subroutines
> that have a widely agreed upon interface and are supplied with the
> compiler.

Define "normally" and "documented" and "widely agreed upon" for this
context :)

Or, alternatively, have a look at a language standard that contains
library interface definitions (e.g. the C++ standard -- you'll find a
link in this thread to a draft).

If the interface is defined ("documented" in a "standard") -- both in
syntax and semantics --, the compiler writer can rely on this definition
for any high-level optimizations.

I have written what I understand in this context as "standard library"
repeatedly in this thread; just search for it.

> You seem to want intrinsic functions that you can also write yourself
> if you want to.  

No. I've written this already. Conclusions based on this have nothing to
do with what I wrote.

Gerhard

2009\07\22@151032 by Gerhard Fiedler

picon face
sergio masci wrote:

{Quote hidden}

I thought that there was some disconnect, and I hoped that we would get
there eventually :)

{Quote hidden}

I suspect that in many compilers (3) and (2) end up (as an intermediate
representation) in something that's equivalent to (1). But even if not,
it shouldn't be too difficult to make all three end up in the same,
whatever the compiler's internal representation of this statement is.

It's probably a bit more difficult to write a parser for (2) and (3)
than it is to write one for (1), but in the great scheme of a compiler,
I don't think that this difference is crucial.

So, yes, I think for a compiler these three could be identical. I don't
see that a compiler could derive any information from any of them that
it couldn't derive from the other two.

Provided, of course, that the functions used in (1) are just as defined
as the operators and statements used in (2) and (3).

> AND because the compiler should be able to "understand" functions as
> easily as other language statements that it is a convenient way to
> extend the language.

Yes, extend or customize. That's approximately the C++ standard library
way.

(However, in C++ this isn't done thoroughly. Due to notation conventions
and backwards compatibility, many language elements are special
operators with special features; for example, no matter the specific
meaning given through overriding, the relative precedence of operators
is fixed by the language. Probably a good and necessary thing, but
breaks the extendibility. Not having any precedence and requiring
parentheses for everything would be the "clean" way, but that's more
cumbersome to write in a large majority of the cases, so this is not
only backwards compatibility, but also pragmatism.)

> Could you please confirm this.

Basically confirmed.

Gerhard

2009\07\22@153952 by sergio masci

flavicon
face


On Wed, 22 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

Yes Gerhard as Olin says you do seem to want intrinsic functions that you
can also write yourself if you want to.

This is not a bad thing, just incredibly difficult to achive efficiently.
By which I mean have a modern PC capable of generating an executable from
such a compiler in an acceptable time.

By definition, intrinsic means that the compiler understands what these
functions do and how they do it. The exact optimised code generated for
such a function could be contained in a special internal (to the compiler)
macro with lots of conditional assembly going on inside it. Or as you have
already suggested, it could be a function held as source (maybe C) which
gets compiled everywhere it is needed (including conditional compilation).
But this would still be intrinsic to the compiler because the compiler
has a preconceived idea of what the function does and the actual source
code for the function would not change this idea.

The function calling protocol would be horrendus (very big and complicated
and much slower to execute than that needed for the standard / normal
function calling protocol) to allow for good optimisation but I can see
that this could be done.

Friendly Regards
Sergio Masci

2009\07\22@164852 by sergio masci

flavicon
face


On Wed, 22 Jul 2009, Gerhard Fiedler wrote:

> Basically confirmed.

Interesting.

Thinking.

Friendly Regards
Sergio Masci

2009\07\22@185551 by sergio masci

flavicon
face


On Wed, 22 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

Ok so I write a seperate parser for all three and internally they all
produce:

       if_statement
       .. expr
       .. .. lt
       .. .. .. x
       .. .. .. 0
       .. statement
       .. .. assign
       .. .. .. y
       .. .. .. 0
       .. statement
       .. .. assign
       .. .. .. y
       .. .. .. x

So what advantage does this give me?

If instead of the keyword 'if' I used a function 'xyz' thus:

       xyz( lt(x, 0), assign(y, 0), assign(y, x) )

my parsers would all now produce:

       expr
       .. func
       .. .. xyz
       .. .. expr
       .. .. .. lt
       .. .. .. .. x
       .. .. .. .. 0
       .. .. expr
       .. .. .. assign
       .. .. .. .. y
       .. .. .. .. 0
       .. .. expr
       .. .. .. assign
       .. .. .. .. y
       .. .. .. .. x

Internally the compiler has different sections that deal with generating
code for 'if_statment' trees, 'statement' trees and 'expr' trees.

How would you propose that I treat 'xyz' differently while parsing and how
would you add a specific code generator for the now special 'xyz' (you
need to describe all this somehow)?

e.g.
the 'if_statement' code generator knows that it might have either one or
two statements following the condition expression. It also knows that if
the condition expression evaluates to a compile time constant that it can
discard either the 'true' or 'false' statements. It also needs to interact
with the code generator for the condition expression to allow that
generator to produce efficient optimised code jumps to the 'true' or
'false' statements (think of early out logical expressions involving '&&'
and '||'). Consider the difference between "if (cond)..." and "X=cond"

>
> It's probably a bit more difficult to write a parser for (2) and (3)
> than it is to write one for (1), but in the great scheme of a compiler,
> I don't think that this difference is crucial.
>
> So, yes, I think for a compiler these three could be identical. I don't
> see that a compiler could derive any information from any of them that
> it couldn't derive from the other two.

Actually it can. Consider a long complex program made up purely of
functions as in (1). What happens with a misplaced comma or parenthesis?
The verbose syntax lets the compiler catch silly mistakes. Consider the
difference between:

       if (...)
       {
               a = b;
       }

       while (...)
       {
               c = d;
       }

and
       if ... then
       endif

       while ... do
       done

Now edit the above:


       if (...)
       {
               while (...)
               {
                       a = b;
               }

               c = d;
       }

and
       if ... then

               while ... do
                       a = b;
               endif

               c = d;
       done


>
> Provided, of course, that the functions used in (1) are just as defined
> as the operators and statements used in (2) and (3).

Ok so I'll give you that, all the functions are defined in exactly the
same way in (1) as they are in (2) and (3). But what are we going to do
about the vast number of functions defined in the /standard/ library?

>
> > AND because the compiler should be able to "understand" functions as
> > easily as other language statements that it is a convenient way to
> > extend the language.
>
> Yes, extend or customize. That's approximately the C++ standard library
> way.

But the C++ way is horrible! You have CLASS upon CLASS upon CLASS. If you
want to write a modest program you end up so deep in 'standard' classes
and templates that it gets very hard to see the wood for the trees.

This nonsense that user classes should be written in such a way as to have
special methods that the standard libraries expect (things like iterators)
so that the items in a container can be accessed. The programmer shouldn't
need to know about all this. He should be able to just say (e.g.)

       for all items in list FRED do

               *.x = $.x + 1
       done

> > Could you please confirm this.
>
> Basically confirmed.

Friendly Regards
Sergio Masci

2009\07\25@004640 by Gerhard Fiedler

picon face
sergio masci wrote:

{Quote hidden}

I don't know, but if you do it, you probably know :)  Seriously, I don't
understand the question in this context.

{Quote hidden}

'if' is a special statement/construct/function, defined in the language
standard. 'xyz' is not. Therefore, the compiler can have (and generally
has) special code to generate 'if' more efficiently than a function
call.

Compared to the original issue -- lists --, 'if' is much more simple,
and the function call overhead here is important and more than the
actual functionality typically would be. That's why it generally makes
sense to implement such a construct directly, avoiding the function call
overhead.

I'm not a compiler specialist, but it could be that 'avoiding the
function call overhead' is a premature optimization, and that a later,
lower-level optimization could result in just this. In any case, since
'if' is defined in the language standard, there's nothing that would
prevent a compiler writer to implement it in the compiler.

> the 'if_statement' code generator knows that it might have either one
> or two statements following the condition expression. It also knows
> that if the condition expression evaluates to a compile time constant
> that it can discard either the 'true' or 'false' statements. It also
> needs to interact with the code generator for the condition
> expression to allow that generator to produce efficient optimised
> code jumps to the 'true' or 'false' statements (think of early out
> logical expressions involving '&&' and '||'). Consider the difference
> between "if (cond)..." and "X=cond"

Yes. This all is pretty much C. I thought we weren't really talking
about any specific languages, but about 'implemented in the compiler'
versus 'implemented in a library'.

The 'if' statement implementation is so short that going through a
general-purpose function call convention would blow up the code
tremendously. But:
1) Nobody says that the compiler writer /has/ to do this. The 'if'
statement is defined in the language standard, and the compiler writer
can choose to implement it directly in the compiler.
2) Even if the compiler writer chooses to implement it as function call,
I think it is possible that a lower-level optimization detects the
inefficiencies and successfully optimizes the function call away
(remember that I considered that the function is available as source),
reaching the same code as if implemented directly.

>> So, yes, I think for a compiler these three could be identical. I
>> don't see that a compiler could derive any information from any of
>> them that it couldn't derive from the other two.
>
> Actually it can. Consider a long complex program made up purely of
> functions as in (1). What happens with a misplaced comma or
> parenthesis?

That's a feature of that specific syntax, not a difference whether the
'if' function is implemented in the compiler or in a library. We didn't
discuss the various merits of the different syntaxes (sp ?? :)

> The verbose syntax lets the compiler catch silly mistakes.

Of course. The more redundant (that is, verbose) the syntax is, the
easier it is both for the programmer to get something wrong and for the
compiler to catch when something is wrong. But we didn't discuss the
merits of different syntaxes, we discussed merits of 'implemented in the
compiler' versus 'implemented in a standard library'.

>> Provided, of course, that the functions used in (1) are just as
>> defined as the operators and statements used in (2) and (3).
>
> Ok so I'll give you that, all the functions are defined in exactly
> the same way in (1) as they are in (2) and (3). But what are we going
> to do about the vast number of functions defined in the /standard/
> library?

I don't understand the question. I didn't mean to suggest that all
functions need to have an equivalent in the forms (2) or (3), but rather
the other way round, that typically constructs of the forms (2) or (3)
have an equivalent function call syntax that does the same
(functionally, not necessarily in terms of typing or user-friendliness).


{Quote hidden}

This is not about a specific implementation of the principle, this is
about the principle. You always bring in C, despite (or because?) we
already agreed that the C way is pretty much horrible. And we probably
can agree that the BASIC way is horrible, too -- some exceptions
notwithstanding :)

{Quote hidden}

I don't really understand this. This is probably your syntax, and quite
familiar to you, but I don't think a majority of list readers here would
know what this does. In any case, I don't.

Anyway, for what it's worth, and independently of the issue we're
discussing (compiler-built-in vs standard-library-implemented), my C++
code looks similar:

BOOST_FOREACH( item i, FRED ) {
 ++i.x;
}

(If this is what your code does... since I don't know what it does, I
can't really tell, but it probably is trivial to correct it if it's
doing something different. And I don't generally use identifiers like
FRED for lists in C++, but that's only a style question.)

But again, this is not a discussion of C++ style syntax versus BASIC
style syntax (yet :) -- and I don't see anything particularly
advantageous about the C++ style syntax. But all of C++'s list handling
is implemented in libraries -- and that's the issue.

(I used here an element from the Boost library. It's not a standard
library, but it could be one. Whether or not a given library is a
standard library is just a matter of definition, and not of principle.)

Gerhard

2009\07\25@104234 by olin piclist

face picon face
Gerhard Fiedler wrote:
> Of course. The more redundant (that is, verbose) the syntax is, the
> easier it is both for the programmer to get something wrong and for
> the compiler to catch when something is wrong.

Not necessarily, and this is one of the problems with C.  It's not always as
obvious to a human when the wrong special character is used, for example,
than a more verbose keyword.  It is easier to get "{" or "}" wrong than the
more verbose "begin" or "end", for example.  The latter are bigger patterns
to match against and more obvious when they are wrong, especially to a
casual observer.

I had exactly this case last week.  I added one more symbol to a C ENUM, and
apparently typed ")" instead of "}" to close the list.  These two look
fairly similar, so I didn't notice.  That, and the fact that I don't do C
that often caused several wasted minutes trying to figure out why the code
wouldn't compile.  The C18 compiler's cryptic "syntax error on line xxxx"
didn't exactly help either.

I'm pretty sure that if I had been required to type END or something more
verbose than "}", the mistake would never have happened or I would have
noticed it much quicker.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\25@181426 by Alan B. Pearce

face picon face
>The C18 compiler's cryptic "syntax error on line xxxx"
>didn't exactly help either.

C30 is like this as well. It knows there is a syntax error in that it has
reached something without finding a closing bracket, why does it need to use
a catch-all error message???

2009\07\25@195025 by sergio masci

flavicon
face


On Sat, 25 Jul 2009, Alan B. Pearce wrote:

> >The C18 compiler's cryptic "syntax error on line xxxx"
> >didn't exactly help either.
>
> C30 is like this as well. It knows there is a syntax error in that it has
> reached something without finding a closing bracket, why does it need to use
> a catch-all error message???
>

Because at that level of parsing it may just be looking for any one of a
set of tokens. The "catch-all error message" just means it found something
it wasn't expecting (not in the list, maybe a keyword, brace or
semicolon). At that level the function doesn't know what it's parsing so
it can't tell you what the real problem is.

Friendly Regards
Sergio Masci

2009\07\25@200121 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

> Gerhard Fiedler wrote:
>> Of course. The more redundant (that is, verbose) the syntax is, the
>> easier it is both for the programmer to get something wrong and for
>> the compiler to catch when something is wrong.
>
> Not necessarily, and this is one of the problems with C.  

What "not necessarily"? Sometimes, it seems you don't really try to
understand and go against, just because... :)

> It's not always as obvious to a human when the wrong special character
> is used, for example, than a more verbose keyword.  

This is what I wrote: the more verbose, the easier to catch ("more
obvious") when something is wrong.

> It is easier to get "{" or "}" wrong than the more verbose "begin" or
> "end", for example.  

I think here you're wrong. The probability to type a wrong letter is
about the same per letter, so the probability to type "begin" wrong is
higher than the probability to type "{" wrong.

> The latter are bigger patterns to match against and more obvious when
> they are wrong, especially to a casual observer.

Exactly... for the reviewer or for the compiler, it's much easier to
catch the error with "begin" than with "{". This is what I wrote. So
again: what "not necessarily"?


> I had exactly this case last week.  I added one more symbol to a C
> ENUM, and apparently typed ")" instead of "}" to close the list.
> These two look fairly similar, so I didn't notice.  That, and the
> fact that I don't do C that often caused several wasted minutes
> trying to figure out why the code wouldn't compile.  The C18
> compiler's cryptic "syntax error on line xxxx" didn't exactly help
> either.

It seems that the compiler didn't have a problem detecting that there
was something wrong. That the compiler didn't provide you with a helpful
error message is another issue -- that's not a problem with language
syntax but with the specific compiler implementation.

> I'm pretty sure that if I had been required to type END or something
> more verbose than "}", the mistake would never have happened or I
> would have noticed it much quicker.

You can define preprocessor macros and use Begin and End instead of {
and }.

Gerhard

2009\07\25@200630 by Gerhard Fiedler

picon face
sergio masci wrote:

>>> You seem to want intrinsic functions that you can also write
>>> yourself if you want to.  
>>
>> No. I've written this already. Conclusions based on this have
>> nothing to do with what I wrote.
>
> Yes Gerhard as Olin says you do seem to want intrinsic functions that
> you can also write yourself if you want to.
>
> This is not a bad thing, just incredibly difficult to achive
> efficiently. By which I mean have a modern PC capable of generating
> an executable from such a compiler in an acceptable time.
>
> By definition, intrinsic means that the compiler understands what
> these functions do and how they do it.

I already wrote a few times that what I'm thinking are functions for
which the compiler writer knows what they do, but not necessarily how
they do it (that is, they may be implemented in a library, not
necessarily by the compiler)?

> But this would still be intrinsic to the compiler because the compiler
> has a preconceived idea of what the function does and the actual source
> code for the function would not change this idea.

Calling a function with a standard interface ("preconceived idea of what
it does") and an implementation in a library for which source code is
available "intrinsic" is against every common use of this word.
Including against your own... you already said that you don't consider
the C++ function std::list::insert an intrinsic function. But it's this
type of function that I'm talking about.

Gerhard

2009\07\25@212134 by Russell McMahon

face picon face
> Gerhard
>>> Of course. The more redundant (that is, verbose) the syntax is, the
>>> easier it is both for the programmer to get something wrong and for
>>> the compiler to catch when something is wrong.

Olin:
>> Not necessarily, and this is one of the problems with C.

Gerhard:
> What "not necessarily"? Sometimes, it seems you don't really try to
understand and go against, just because... :)
FWIW, and this is entiely about understanding each other's language, and not
about understanding 'the machine's' language, I read what Olin wrote,
understood it and largely agreed with it and it SEEMS to me that he
understood you but that you misunderstand him. He seems to have an entiely
valid point and to be addreessing a real issue. ("But,", as Sagan was wont
to say , "I may be wrong" :-) ).

This is NOT a criticism - just an observation.
And it may be wrong in fact.

>> It's not always as obvious to a human when the wrong special character
>> is used, for example, than a more verbose keyword.

>This is what I wrote: the more verbose, the easier to catch ("more
>obvious") when something is wrong.
To my ear/brain/eye [ebe], that is NOT what you wrote - My ebe says that you
are say ing the opposite of what Olin is saying.

> It is easier to get "{" or "}" wrong than the more verbose "begin" or
> "end", for example.

ie Olin is saying NOT that by random typing error you are more liable to get
a single character errot (which, as you correctly note, is not the case, on
a purely statistical basis. He is saying that if one substitutes any one of
{ or } or ) or ( incorrectly for some other member of the set, then one is
more likely to miss the eeeor than if one puts begin when one should have
put end.
Whereas { for } is a typo,

   begin
       blah blah blah
   begin

is a 'braino' which one would not makev (except on bank holidays at new moon
in a fish market).

You said (my ebe says)
    People are liable to make more mistakes and machines
    less with multi-character symbols compared to single
    character sumbols.

> I think here you're wrong. The probability to type a wrong letter is
> about the same per letter, so the probability to type "begin" wrong is
> higher than the probability to type "{" wrong.

As above - Olin was talking about mental parsing, not about statistical
typing erros.

>> The latter are bigger patterns to match against and more obvious when
>> they are wrong, especially to a casual observer.

> Exactly... for the reviewer or for the compiler, it's much easier to
catch the error with "begin" than with "{". This is what I wrote. So
again: what "not necessarily"?
/>

No. You actually said the opposite FOR A PERSON (my ebe says).

> > I had exactly this case last week.  I added one more symbol to a C
>> ENUM, and apparently typed ")" instead of "}" to close the list.
>> These two look fairly similar, so I didn't notice.  That, and the
>> fact that I don't do C that often caused several wasted minutes
>> trying to figure out why the code wouldn't compile.  The C18
>> compiler's cryptic "syntax error on line xxxx" didn't exactly help
>> either.
>It seems that the compiler didn't have a problem detecting that there
>was something wrong.

Yes. Which is his point. Olin had problems with the single character symbol.
The compiler didn't. That is the point he was making and the one that you
SEEMED to be opposing.


>That the compiler didn't provide you with a helpful
>error message is another issue -- that's not a problem with language
>syntax but with the specific compiler implementation.

Yes.

> I'm pretty sure that if I had been required to type END or something
> more verbose than "}", the mistake would never have happened or I
> would have noticed it much quicker.
You can define preprocessor macros and use Begin and End instead of {
and }.

Yes.
The main point (possibly :-) ) is that the double ended sharp bladed light
sabre has no guards on either end as that's the way the original expert
liked it, but when playing with it it's easy to lose a finger.
One can, of course, use a preprocessor to add guards and a scabbard.
Some of the 'expert' features are harder to "fix" with simple text
substitution pre-processing. eg the (if I recall the argument correctly)
fall through CASE treatment which the original expert probably didn't mind
but which allows people to make mincemeat of their programs if they do not
understand that it diffres from more protective languages.


    Russell

      Russell

2009\07\26@020815 by Gerhard Fiedler

picon face
Russell McMahon wrote:

>> Gerhard
>>>> Of course. The more redundant (that is, verbose) the syntax is, the
>>>> easier it is both for the programmer to get something wrong and
>>>> for the compiler to catch when something is wrong.
>
> Olin:
>>> Not necessarily, and this is one of the problems with C.
>
> Gerhard:
>> What "not necessarily"? Sometimes, it seems you don't really try to
>> understand and go against, just because... :)


> FWIW, and this is entiely about understanding each other's language,
> and not about understanding 'the machine's' language, I read what
> Olin wrote, understood it and largely agreed with it ...

So did I (even before he wrote :), in case I didn't get this over
properly.

> ... and it SEEMS to me that he understood you but that you
> misunderstand him.

Or both of you misunderstood what I wrote first? Not impossible
either... for a variety of reasons :)

>>> It's not always as obvious to a human when the wrong special
>>> character is used, for example, than a more verbose keyword.
>
>> This is what I wrote: the more verbose, the easier to catch ("more
>> obvious") when something is wrong.
>
> To my ear/brain/eye [ebe], that is NOT what you wrote - My ebe says
> that you are say ing the opposite of what Olin is saying.

Ok... this seems to become a language (English, not C) or a thought
process issue. In my understanding, part of what I wrote is:

"The more redundant (that is, verbose) the syntax is, the easier it is
... for the compiler to catch when something is wrong."

I wrote "for the compiler", but the important issue is not the compiler,
but that it's easier to catch an error (or even correct it) when the
information is redundant. See your typo a few sentences below... easy to
correct, because the language provides sufficient redundancy.

>> It is easier to get "{" or "}" wrong than the more verbose "begin" or
>> "end", for example.
>
> ie Olin is saying NOT that by random typing error you are more liable
> to get a single character errot (which, as you correctly note, is not
> the case, on a purely statistical basis.

Agreed. So we seem to agree that it's more likely to type "begon" (or
any of the other possible, wrong variants) instead of "begin" than "}"
(or any of the other possible, wrong variants) instead of "{". And that
it is more likely for the compiler to catch the "begon" typo than the
"}" typo (even though it's quite likely that both won't go uncaught, if
for nothing else then because the balance is off).

> He is saying that if one substitutes any one of { or } or ) or (
> incorrectly for some other member of the set, then one is more likely
> to miss the eeeor than if one puts begin when one should have put
> end.

Agreed. But that's after the fact, when reviewing, not when typing. And,
FWIW, it's most likely that the compiler catches either with equal (and
high) probability -- which is what's probably most important. I think
it's been decades that I had a bug in a C program (a bug, not a "doesn't
compile" error) that was due to an incorrectly typed parenthesis. (And
this doesn't only include my own programs.) If I ever saw one. A decent
language-aware editor already tells you that your
parentheses/brackets/begin-end/whatever pairs are unbalanced before you
even compile.

> Whereas { for } is a typo,
>
>     begin
>         blah blah blah
>     begin
>
> is a 'braino' which one would not makev (except on bank holidays at new moon
> in a fish market).

Agreed. (But IMO this is /not/ what Olin said... this is what you
/thought/ reading his comments :)

But I don't think there is a big difference in the probability that
either will be caught by the compiler, and the probability is quite
high. If you wanted to craft an example, you'd have to quite carefully
do so -- create two such typos that cancel each other out and where the
resulting code still is correct syntax.

> You said (my ebe says)
>      People are liable to make more mistakes and machines
>      less with multi-character symbols compared to single
>      character sumbols.

No (IMO... but you know that my English is sometimes ... how do I say
... odd, at least for a native speaker, and I still, sometimes against
better judgment, use them as the measuring stick :)

What I wrote we know (see above). What I meant, in the terms of this
re-write, could be:

People are liable to make more typos when they have to type more. But
when they have to type more to pass the same information, the implicit
redundancy allows the compiler (and possibly a reviewer) to more easily
catch the typos due to the inconsistencies they create.

(Doesn't apply to all verbosity, but applies to the one we're talking
about.)

{Quote hidden}

I didn't quite oppose what Olin said. With the exception of a rather
unimportant side-issue, I thought that what I wrote originally was
pretty much the same as what Olin wrote, even though looked at from a
slightly different angle. The only thing I really opposed was Olin's
opposition (as expressed in the "not necessarily").

{Quote hidden}

Yes, but we've been there exhaustively, and I think there's no real
disagreement about many of the shortcomings of C (at least not between
the three of us).

Maybe let me add a last clarification... I don't like C and C++ that
much, but I'm quite proficient in both and spend a lot of time with
them.

Bugs due to typos with the language symbols are /very/ rare IME (which
doesn't include only my code; it also includes code reviewed by me and
written by all kinds of programmers). When such typos happen, they are
with a quite high probability caught by the compiler, and with some
experience (and a decent compiler) quickly fixed (Olin's mishap
notwithstanding).

The bugs due to typos that I see are of the kind where you have maybe a
member variable m_balloons and change your logic for a certain function
to work with the function argument a_balloons and changed all instances
of m_balloon but one. The probability of such typos is pretty much
language-independent, and depends largely on other factors.

FWIW, Olin's Pascal-to-C compiler is a sort of elaborate pre-processor
that even takes out the fall-through in the switch :) (Well, I haven't
seen it, but I'm sure it does.)

The brackets-versus-begin/end debate is quite old, and I think there's
not much under the sun that could be said that hasn't already been said.
It's a matter of taste, not much more. The arguments of the fighters on
either side are many, and some on each side do have merit -- but who's
to say how exactly the balance is? For everybody?

Gerhard

2009\07\26@062626 by sergio masci

flavicon
face


On Sat, 25 Jul 2009, Gerhard Fiedler wrote:

> Olin Lathrop wrote:
>
> > I'm pretty sure that if I had been required to type END or something
> > more verbose than "}", the mistake would never have happened or I
> > would have noticed it much quicker.
>
> You can define preprocessor macros and use Begin and End instead of {
> and }.

Noooooooooooooooooooooooooo......... </dispair>

I've seen this done and had to live with it for a while.
Really really REALLY bad idea.

Consider, defined are:

BEGIN        {
END        {

IF if        (
THEN        ) {
ELSE        } else {
ENDIF        }

WHILE        while (
DO        ) {
DONE        }


you find a piece of code that is several pages long and looks like:

       IF ... THEN

       ... // several pages of code here

       DONE

What's the intent of this code? Was it supposed to be a loop or a
conditional? Did the original programmer have a brain fart while writing
this, start out writing a conditional, changed his mind part way through
and finished as if it were a loop (but forgot to go back and change the IF
to a WHILE). Isn't the compiler supposed to give you a kick and force you
to clarify this?


Friendly Regards
Sergio Masci

2009\07\26@062635 by sergio masci

flavicon
face


On Sat, 25 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

Yes I understand this (and I have gone to great pains to ensure that I
understand exactly what you mean).

What you are describing *** ARE *** intrinsic functions because they
become part of the language and are fundamental to the operation of the
compiler. How they are stored on the computer if not important, how
information is extracted from them to generate code is not important. The
fact is the compiler knows about them and their special requirements
to the point where it is able understand the interaction between these
functions (you have made this a requirement). All this said - they are now
intrinsic.

>
> > But this would still be intrinsic to the compiler because the compiler
> > has a preconceived idea of what the function does and the actual source
> > code for the function would not change this idea.
>
> Calling a function with a standard interface ("preconceived idea of what
> it does") and an implementation in a library for which source code is
> available "intrinsic" is against every common use of this word.

No it is not. What you have done is taken an ordinary library and made it
intrinsic while keeping the actual source code of the library accessable
from outside the compiler. Kind of like intrinsic functions with "hooks".

May I remaind you that you yourself suggested that the compiler writer
"knows" what these library functions do because they themselves are
defined in a standard and that this information could be used by the
compiler to understand the interaction between these functions - hence
"preconceived idea of what it does" (this was not some kind of derogetory
remark aimed at you it was simply a statement of fact :)

Part of me like this idea (alternate personality 17 :) and I'd love to
take a few years to go away and play with it - but you are talking about
intrinsic!!!!

> Including against your own... you already said that you don't consider
> the C++ function std::list::insert an intrinsic function. But it's this
> type of function that I'm talking about.

Yes I have already said that I do not consider 'std::list::insert'
intrinsic and I still don't. The reason is simple, there is no specialised
code built into the C++ compiler that looks out for *** AND *** treats
'std::list::insert' in a special way.


Friendly Regards
Sergio Masci

2009\07\26@092722 by olin piclist

face picon face
Gerhard Fiedler wrote:
>>> Of course. The more redundant (that is, verbose) the syntax is, the
>>> easier it is both for the programmer to get something wrong and for
>>> the compiler to catch when something is wrong.
>>
>> Not necessarily, and this is one of the problems with C.
>
> What "not necessarily"? Sometimes, it seems you don't really try to
> understand and go against, just because... :)

I was disagreeing with the part that it's easier for the programmer to get a
verbose syntax wrong, as I illustrated with a actual case.

>> It is easier to get "{" or "}" wrong than the more verbose "begin" or
>> "end", for example.
>
> I think here you're wrong. The probability to type a wrong letter is
> about the same per letter, so the probability to type "begin" wrong is
> higher than the probability to type "{" wrong.

It doesn't work that way.  The probability of typing different letters wrong
are not the same, with special characters being much higher, at least in my
experience.  Anything that requires SHIFT or other control keys is more
error prone.

If you type something a lot, your brain will develop a sortof "macro" for
it.  You no longer conciously type the individual letters, but think of the
whole word.  The probability of getting these keywords wrong is much less
than a new word made of arbitrary letters.  Think of typing "the".  You just
think "the", not t-h-e, and your brain automatically produces the right
keystrokes and very very rarely gets them wrong.

Then there is some sort of checking done in your brain when typing.  I know
it sounds unintuitive, but it seems there is a process that detects mistypes
that is separate from creating the key actions in the first place.  I can't
explain it better, but I think anyone that touch types knows what I mean.  I
can be typing something by looking at the original and not the screen.  When
I make a mistake I somehow know it, even though the same brain made the
mistake in the first place.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\26@094910 by olin piclist

face picon face
Gerhard Fiedler wrote:
> I think
> it's been decades that I had a bug in a C program (a bug, not a
> "doesn't compile" error) that was due to an incorrectly typed
> parenthesis.

Yes, but compile errors still waste time, as was the case in my example.

> People are liable to make more typos when they have to type more.

I guess this is the fundamental disagreement.  I think I'm less likely to
get "end" wrong than "}".  By getting wrong I include the immediate
automatic checking the brain does of the key strokes and you visually do by
watching the screen as you type.  I consider these immediate processes to be
part of the act of typing, with a typo being a error that survives this
process.  See my other post about this automatic checking.

> I didn't quite oppose what Olin said. With the exception of a rather
> unimportant side-issue, I thought that what I wrote originally was
> pretty much the same as what Olin wrote, even though looked at from a
> slightly different angle. The only thing I really opposed was Olin's
> opposition (as expressed in the "not necessarily").

Now I'm really confused ;-)

> FWIW, Olin's Pascal-to-C compiler is a sort of elaborate pre-processor
> that even takes out the fall-through in the switch :) (Well, I haven't
> seen it, but I'm sure it does.)

It does, as Pascal is defined such that when a case exits, the whole CASE
statement is exited.  This is the equivalent of a implied BREAK at the end
of each case of a C SWITCH statement.

By the way, my translator is available via free download.  It is included in
the full runtime release available at http://www.embedinc.com/pic/dload.htm.
The source code is open and included in the "host source code and
everything" release on the same page.


********************************************************************
Embed Inc, Littleton Massachusetts, http://www.embedinc.com/products
(978) 742-9014.  Gold level PIC consultants since 2000.

2009\07\26@102202 by Gerhard Fiedler

picon face
sergio masci wrote:

>> Including against your own... you already said that you don't
>> consider the C++ function std::list::insert an intrinsic function.
>> But it's this type of function that I'm talking about.
>
> Yes I have already said that I do not consider 'std::list::insert'
> intrinsic and I still don't. The reason is simple, there is no
> specialised code built into the C++ compiler that looks out for ***
> AND *** treats 'std::list::insert' in a special way.

Maybe there isn't (do you know for sure?), but there could be (given
that the meaning 'std::list::insert' is just as defined by the language
standard as the meaning of 'else'). Is there any reason why there
couldn't be? I'm still talking about your first example, replacing a
'delete' followed by an 'insert' with a 'replace' (given that all three
a suitably defined).

IMO, if this is a correct replacement, the compiler can make it,
independently whether the three are implemented in a standard library or
by the compiler. IMO, you haven't yet brought up a good reason why not.

Gerhard

2009\07\26@103007 by Gerhard Fiedler

picon face
sergio masci wrote:

>> Olin Lathrop wrote:
>>
>>> I'm pretty sure that if I had been required to type END or something
>>> more verbose than "}", the mistake would never have happened or I
>>> would have noticed it much quicker.
>>
>> You can define preprocessor macros and use Begin and End instead of
>> { and }.
>
> Noooooooooooooooooooooooooo......... </dispair>

I didn't say that I'd find it a good idea :)

{Quote hidden}

Ah... this wouldn't have happened with Pascal-style redefinitions.
Pascal, like C, treats all blocks alike, no matter the statement they're
associated with. In neither language you have a means to distinguish
them, like you do in BASIC. I haven't programmed enough with BASIC to be
able to say whether I'd like it.

Gerhard

2009\07\26@133601 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

>> What "not necessarily"? Sometimes, it seems you don't really try to
>> understand and go against, just because... :)
>
> I was disagreeing with the part that it's easier for the programmer
> to get a verbose syntax wrong, as I illustrated with a actual case.

I can see your point, but being engineer, I don't really think any of us
knows this without having made some real measurements. My experience is
that it's very very rare to get the braces wrong -- so rare that it's a
non-issue in discussing its virtues. There are other, much more
influential problems with any language.

Gerhard

2009\07\26@135611 by Gerhard Fiedler

picon face
Olin Lathrop wrote:

>> I think it's been decades that I had a bug in a C program (a bug, not
>> a "doesn't compile" error) that was due to an incorrectly typed
>> parenthesis.
>
> Yes, but compile errors still waste time, as was the case in my
> example.

I see that, but IME it is negligible. YMMV, of course... after all, it's
not for nothing that you wrote a Pascal-to-C compiler :)


>> People are liable to make more typos when they have to type more.
>
> I guess this is the fundamental disagreement.  I think I'm less
> likely to get "end" wrong than "}".  By getting wrong I include the
> immediate automatic checking the brain does of the key strokes and
> you visually do by watching the screen as you type.  I consider these
> immediate processes to be part of the act of typing, with a typo
> being a error that survives this process.  See my other post about
> this automatic checking.

As I responded there, I can see that, but I still think it's negligible.

OTOH, I almost never type "}" -- I have my editor do this. Whenever I
type "{", it inserts the next line, indents it, puts the cursor there,
and inserts the closing brace a line below. Whenever I want to wrap a
sequence of lines into braces, I mark it, type "{" and the editor does
its job (adding "{" at the start, "}" at the end, indenting the marked
lines). If I type a "}" where I meant a "{", I see this immediately very
clearly: firstly, because the expected expansion didn't follow, and
secondly because if there's now an imbalance in the braces, the not
matched ones are highlighted.

To end the discussion (going back to the beginning of C and Pascal :)
whether braces or begin/end are better, compilers (both C and Pascal)
could come with a switch that allows the user to choose :)  Of course,
Sergio would say that both languages got it wrong...


>> I didn't quite oppose what Olin said. With the exception of a rather
>> unimportant side-issue, I thought that what I wrote originally was
>> pretty much the same as what Olin wrote, even though looked at from
>> a slightly different angle. The only thing I really opposed was
>> Olin's opposition (as expressed in the "not necessarily").
>
> Now I'm really confused ;-)

This is a good thing, occasionally :)

Basically, I think the difference stems from two "boundaries" that are
different:

"I consider these immediate processes to be part of the act of typing
..."

I considered "typing" only the typing.

"... with a typo being a error that survives this process."

I considered the really problematic typo the one that survives both this
process and the compiler checks.


> By the way, my translator is available via free download.  It is
> included in the full runtime release available at
> http://www.embedinc.com/pic/dload.htm. The source code is open and
> included in the "host source code and everything" release on the same
> page.

I've said this before, and I think it's worth repeating. Besides all our
differences, I admire the effort you put into your tools -- and the fact
that you make much of that publicly available. And if more people who
use C put a similar effort in their environment, much of what gives C
the bad rep wouldn't be there.

Gerhard

2009\07\27@144611 by sergio masci

flavicon
face


On Fri, 24 Jul 2009, Gerhard Fiedler wrote:

{Quote hidden}

Ok, I understand now, you're talking about going backwards (everything
towards the type (1) syntax) whereas I was saying something else - see
below.

{Quote hidden}

But it's not just the function call overhead that's important here.

If we were to implement the 'if' statement as a function the calling
protocol would be completely different to that of a normal function
regardless of any special optimisations.

In the 'if' statement, either the 'true' or 'false' statement is executed
only *** AFTER *** the 'if' condition is evaluated. In the 'if' function,
the condition and both the 'true' and 'false' statements (all 3 parameters
of the 'if' function) are evaluated before the 'if' function is called.

Trying to say that you can achine the same functionality by extending the
language using functions as you can by adding special keywords does not
hold. You'd have to say "some functions are called like, some are called
like that, some are called in bizzaro mode N etc etc etc..." The whole
thing would become a mess and you've been forced to change the way the
language works anyway :)

I am trying to show that internally there is a fundamental difference
between the way statements are parsed and code is generated for them and
functions are parsed and code is generated for them. Just because you
parse both and generate trees for both it doesn't mean that the trees are
the same.

Ok, so I'll go along with you on this and I'll trap certain functions in
my 'new' compiler so that they give you the result you want (delayed
evaluation of parameters). But can you not see that the amount of work
going into the compiler proper (by the compiler writer) is huge. The
language looks like it's being extended by adding functions but these
functions have a large component buried inside the compiler. So these
functions (in the /standard/ library) apart from having the illusion of
being external to the compiler are now fundamental to it and could cause
the compiler to generate bad code if they are touched.

The only thing I can see that you might gain from this is better
optimisation of old code.

>
> I'm not a compiler specialist, but it could be that 'avoiding the
> function call overhead' is a premature optimization, and that a later,
> lower-level optimization could result in just this. In any case, since
> 'if' is defined in the language standard, there's nothing that would
> prevent a compiler writer to implement it in the compiler.

Yes but the point isn't about making the 'if' function behave like an 'if'
statement it's about how do make other functions also behave in a special
way without doing a lot of work in the compiler to treat each function as
a special case.

If you're going to do all this extra work to the compiler don't kid
yourself that the /standard/ library is actually helping the compiler
writer - it isn't.

The /standard/ library only came into being to help the user get around
shortcomings in the language and it's only helping the compiler writer if
he/she doesn't need to do anything special with it.

{Quote hidden}

I'm not talking specificaly about C that was just an example so people
could relate. Other languages provide early out logical expressions and
the ability to assign the result of a condition to a variable. It wouldn't
have helped much if I'd written the example in ALGOL. So I'm not pointing
the finger at C and saying "see C is bad", I'm saying "look when you
evaluate a logical expression there's more to it than just a simple is
'x==y' and you need to be able to cope with all kinds of nasty stuff"

{Quote hidden}

I really don't think you would be able to have an 'if' function as source.
How would you describe the function to the compiler if you have no
built-in conditional statement? Would you resort to assembler? How would
you end up optimising this? Would your compiler need a built-in simulator
to be able to run the code internally? I mean if you have a cross compiler
that runs on a PC and it generates code for a PIC would you need a PIC
simulator inside your compiler to be able to execute the assembler for the
'if' function?


{Quote hidden}

But one of the points I've been making all along is having the compiler
identify errors.

{Quote hidden}

Ok so if I understand you correctly what you are saying is "if any program
written in syntax "X" can be converted to the equivalent as if it had
actually been written in syntax (1) (the function call syntax), then the
function call syntax is powerful enough to do anything that a much more
complex syntax would allow". This is what you are saying right?

Ok assuming you are. The problem with this is the intelligence needed
within the compiler to understand the intent of the programmer. This is
what I've been pointing at all along. Ok so I haven't gotten my point
across.

Look, it's like this: any (correct) high level language program can be
converted by a compiler into a machine code executable (by definition
that's what compilers do), but taking an executable and going the other
(using a program to convert it to high level language source) is very
difficult.

The higher the level of the language you want the "de-compiler" to convert
to the harder it gets. The ultimate would be to say "this decompiler
explains in common english what this executable does (a documentor?)".

If you use a higher level language than C (with built-in STRINGS, LISTS,
STACKS, MULTITASKING etc) you are starting from higher level and therefor
impart greater "intent" into your program.

It's like me saying "turn on lamp commected to relay 6" and the compiler
saying "wait a minute you don't have a lamp on relay 6 you have freezer
connected to that relay". As opposed to saying "PORTB |= 1 << 3".

As I tried to show in an earlier post (where I showed many different ways
to append the ascii representation of a number to a string), trying to
understand the intent of a programmer by looking at lots of function calls
is *** VERY ***  difficult.

{Quote hidden}

No, this is not familiar to me at all. I made it up on the spur of the
moment. It propbably doesn't make sense because

       *.x = $.x + 1

should read

       $.x = $.x + 1

:-)

>
> Anyway, for what it's worth, and independently of the issue we're
> discussing (compiler-built-in vs standard-library-implemented), my C++
> code looks similar:
>
> BOOST_FOREACH( item i, FRED ) {
>   ++i.x;
> }

There you go then, you could have had a reasonable go at understanding
what I wrote :)

{Quote hidden}

You keep refering back to BASIC. Do you think I'm pushing BASIC here? I'm
thinking about other things here like SQL, COBOL, ALGOL ICON (you should
really look at ICON - lovely language, lots of built in types).

Friendly Regards
Sergio Masci


'[TECH] language - was [PIC] using BREAK in 'C''
2009\08\09@054253 by Wouter van Ooijen
face picon face
> C30 is like this as well. It knows there is a syntax error in that it has
> reached something without finding a closing bracket, why does it need to use
> a catch-all error message???

- because the C syntax is so 'dense' that in most cases there is more
than one possible correct continuation (and probably at more than one
point in the line)
- because in the presence of macro's it makes no sense to indicate the
position in the line which caused the error
- because of the above most C parser (scanner/tokenizer/lexer) are
bottom-up parsers, optimized for speed, not for accurate error reporting
- most C compilers seem to think it is more important to continue
compiling in order to report more errors than to report errors accurately

Back in my Jal days some people critized me for writing my own top-down
parser. Like most compilers for Algol-type languages it reported the
first error (and only the first), but fairly accurately, bot in position
and in the kind of error.

--

Wouter van Ooijen

-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu

2009\08\09@122056 by M.L.

flavicon
face
On Sun, Aug 9, 2009 at 5:42 AM, Wouter van Ooijen<KILLspamwouterKILLspamspamvoti.nl> wrote:
> Back in my Jal days some people critized me for writing my own top-down
> parser. Like most compilers for Algol-type languages it reported the
> first error (and only the first), but fairly accurately, bot in position
> and in the kind of error.


I think I would normally prefer useful error messages rather than the
C style where you might get 100 errors because of one missing '}'

--
Martin K.

2009\08\09@132525 by Wouter van Ooijen

face picon face
> I think I would normally prefer useful error messages rather than the
> C style where you might get 100 errors because of one missing '}'

So do I, and so do all students I ever had. But C (and some other)
compilers seem to boost mainly their ability to generate tight code.

The computer industry is full of historical artifacts. Why multipass
compilers (now almost extinct)? A stone -age compiler could just contain
a single pass.. Why make only a single pass over the source input? The
stone-ago compiler could contain only a single pass, the input was on
cards or magtape or papertape. Why separate compilation? Why a separate
linking stage? Why find as many errors as you can in one run? You can
probably guess.

For the more advanced guessers: why does the ASCII character DEL have
the value 0x7F, and what is its exact meaning?

--

Wouter van Ooijen

-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu

2009\08\09@135950 by Jan-Erik Soderholm

face picon face
Wouter van Ooijen wrote:

> For the more advanced guessers: why does the ASCII character DEL have
> the value 0x7F, and what is its exact meaning?
>

"All (7) holes punched".


2009\08\09@142933 by Wouter van Ooijen

face picon face
Jan-Erik Soderholm wrote:
> Wouter van Ooijen wrote:
>
>> For the more advanced guessers: why does the ASCII character DEL have
>> the value 0x7F, and what is its exact meaning?
>>
>
> "All (7) holes punched".

If you were a student that would be the problematic type of answer,
because it is totally correct, but does not prove that you understand
why. Which might mean that the question was badly done...

So why is DEL "all holes punched", and what does it mean? For instance,
does it mean "delete the previous character", like a backspace?

--

Wouter van Ooijen

-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu

2009\08\09@153506 by Jan-Erik Soderholm

face picon face


Wouter van Ooijen wrote:
> Jan-Erik Soderholm wrote:
>> Wouter van Ooijen wrote:
>>
>>> For the more advanced guessers: why does the ASCII character DEL have
>>> the value 0x7F, and what is its exact meaning?
>>>
>> "All (7) holes punched".
>
> If you were a student that would be the problematic type of answer,
> because it is totally correct, but does not prove that you understand
> why. Which might mean that the question was badly done...

No I do not think it was. :-)
It was a perfectly valid question.
And a good one... :-)

>
> So why is DEL "all holes punched", and what does it mean? For instance,
> does it mean "delete the previous character", like a backspace?
>

It replaces what was there before in the same position
on the punched tape with what could be seen as a "NOP".
If my memory doesn't fail me...

2009\08\09@165732 by Wouter van Ooijen

face picon face
> It replaces what was there before in the same position
> on the punched tape with what could be seen as a "NOP".
> If my memory doesn't fail me...

Totally correct. (not surprising, knowing that you are a bit older than
my average student)

--

Wouter van Ooijen

-- -------------------------------------------
Van Ooijen Technische Informatica: http://www.voti.nl
consultancy, development, PICmicro products
docent Hogeschool van Utrecht: http://www.voti.nl/hvu

2009\08\09@170659 by Harry H. Arends

flavicon
face
Found this in a old manual, yes i am 50+ :-)

CORRECTION OF ERRORS Errors on punched tape may be corrected in
various ways, depending upon the
type of error and when it is noticed. Three correction techniques are
explained
here.
The easiest correction is for an error which is detected immediately
after the
wrong key has been depressed. In this case, one need only
1. Turn the FEED KNOB on the left side of the punch back one notch.
2. Depress the CODE DELETE lever once.
3. Continue punching by depressing the proper key on the keyboard.
If a wrong key is depressed whose tape code is a portion of the
desired combination,
the operator need only back the tape until the incorrect character is
under
the punch head, and overpunch it with the proper key. This method is
particularly
useful when the error is detected after characters have been punched
beyond the
error. However, it can only be used when the erroneous and correct
tape codes
are related in the proper way. For example, a "6" can be overpunched
on a "O",
"2", or "4", but not on "5" since the tape code for 5 has a punch in
channel 4
while that for "6" does not.

Harry
{Quote hidden}

> -

2009\08\09@172105 by Jan-Erik Soderholm

face picon face
Wouter van Ooijen wrote:
>> It replaces what was there before in the same position
>> on the punched tape with what could be seen as a "NOP".
>> If my memory doesn't fail me...
>
> Totally correct. (not surprising, knowing that you are a bit older than
> my average student)
>

Probably correct... :-)

Found a nice page with the historical background
to the lower 32 "control chars" (and DEL) in the ASCII table.

http://nemesis.lonestar.org/reference/telecom/codes/ascii.html

A *lot* of intersting historical facts about computing in
general there ! :-)

Enjoy.

Jan-Erik.

2009\08\10@040354 by Alan B. Pearce

face picon face
>For the more advanced guessers: why does the ASCII character
>DEL have the value 0x7F, and what is its exact meaning?

Because you could hand punch a paper tape to the DEL character, whatever it
was before. I believe there were metal guides that you could clip on the
tape to do this, but don't ever recall seeing one in the flesh.

2009\08\11@072627 by Gerhard Fiedler

picon face
Wouter van Ooijen wrote:

>> C30 is like this as well. It knows there is a syntax error in that it
>> has reached something without finding a closing bracket, why does it
>> need to use a catch-all error message???
>
> - because the C syntax is so 'dense' that in most cases there is more
> than one possible correct continuation (and probably at more than one
> point in the line)
> - because in the presence of macro's it makes no sense to indicate the
> position in the line which caused the error
> - because of the above most C parser (scanner/tokenizer/lexer) are
> bottom-up parsers, optimized for speed, not for accurate error reporting
> - most C compilers seem to think it is more important to continue
> compiling in order to report more errors than to report errors accurately

FWIW, the error messages of the C++ compilers I generally work with
point right to the problematic line (or the following line). And when
not, the message is specific enough to easily find the line. VC++ for
example also can be configured to break on first error.

After writing a few days' worth of code and recompiling, I generally get
a few syntax errors. These are pretty much really quick fixes; not much
thinking involved, due to the good locality and appropriate content of
the messages.

Gerhard

More... (looser matching)
- Last day of these posts
- In 2009 , 2010 only
- Today
- New search...