Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

matters of ordering, ...

13 views
Skip to first unread message

BGB / cr88192

unread,
May 18, 2010, 11:13:35 AM5/18/10
to
well, here is some thing I am not really sure of.

sorry if I missed the relevant sections in the standard...


basically, sometimes things may be placed in unusual orders, for example:
int * volatile x;
but, I am not particularly certain what the semantic difference is from:
int volatile *x;

my guess is that the former means x is volatile but the pointed-to memory is
not, and the latter that the referenced memory is volatile but x is not (or
maybe it is the reverse).

my compiler though more naively just applies volatile to both, since
otherwise likely I would need additional set of flags to differentiate these
cases.

similar applies to const / ..., but for the most part my compiler currently
ignores const in most cases.


though, outside standard C, a similar issue applies to __declspec and
__attribute__, which may appear in all sorts of places and I am not sure
what if-any difference this makes semantically (my compiler has to deal with
these since they tend to be in the headers).

(previously, my preprocessor was used to strip them out, but this is no
longer done and they are actually parsed).


example:
__attribute__((foo)) void func();
vs:
void func() __attribute__((foo));

or:
__declspec(bar) struct tagFOO { ... };
vs:
struct __declspec(bar) tagFOO { ... };
vs, say:
struct tagFOO { ... } __attribute__((bar));
...

as-is, my compiler ignores the relative placement of __declspec and
__attribute__ modifiers (technically, they all go into the "root type" of
the declaration, which in the case of functions is attached to the return
type).

also unclear is if I should bother to distinguish them at the AST level (I
guess depends mostly on if there is a risk of clashing names with divergent
semantics...).

actually, as a general rule my compiler currently ignores them anyways.


well, in my recent efforts I have a few other related uncertainties, but
they are not directly related to C...


also, a mystery:
is it "fairly safe" to parse out C++ constructs as well while still in C
mode, or is it better to be more pedantic and allow for C code which would
otherwise clash with a C++ compiler (such as using C++ keywords as
identifiers, ...)?... (IOW, should C++ syntax features be disabled in the
parser in C mode?...).

void this()
{
int dynamic_cast;
int string;
...
if(dynamic_cast<string>3)
...
...
}

where relevant, I have allowed some C++-like features to be used in C mode
via renaming the keywords, such as:
__namespace {
__using ...;
__class Foo {
...
};
...
}

but granted this is ugly, and I am not certain if it is really necessary, or
if one can be more flexible and assume that in their good graces programmers
will not step needlessly on C++ syntax?...

or, if it would be better to just compile things in "C++" mode, even if the
implementation is far from complete and probably never will be...

also possible could be to have the syntax enabled by default and provide an
option to disable it?...


well, this and some amount of CLR-related funkiness MS puts in their
headers, ...


or such...


James Kuyper

unread,
May 18, 2010, 11:02:32 PM5/18/10
to
BGB / cr88192 wrote:
> well, here is some thing I am not really sure of.
>
> sorry if I missed the relevant sections in the standard...
>
>
> basically, sometimes things may be placed in unusual orders, for example:
> int * volatile x;
> but, I am not particularly certain what the semantic difference is from:
> int volatile *x;

The basic rule is that qualifiers (const and volatile) qualify the thing
to the right of them. 'int * volatile x' means that 'x', the pointer
object, is volatile. 'int volatile * x' means that *x, the thing being
pointed at, is volatile.

> my guess is that the former means x is volatile but the pointed-to memory is
> not, and the latter that the referenced memory is volatile but x is not

Correct.

> ... (or

> maybe it is the reverse).

Incorrect.

> my compiler though more naively just applies volatile to both, since
> otherwise likely I would need additional set of flags to differentiate these
> cases.

If the only thing you do with the incorrectly applied 'volatile'
qualifier is to turn off optimizations involving the relevant
expressions, there's no problem.

However, if the incorrectly applied 'volatile' qualifier prevents your
compiler from generating a mandatory diagnostic, or causes it to reject
strictly conforming code, then your compiler is non-conforming.

> similar applies to const / ..., but for the most part my compiler currently
> ignores const in most cases.

Ignoring 'const' almost certainly renders your compiler non-conforming.
While 'volatile' is primarily about optimization, which can always be
skipped, the primary purpose of 'const' is the diagnostics which become
mandatory when it is misused. If your compiler doesn't generate them,
you're doing your users a major disservice.

> also, a mystery:
> is it "fairly safe" to parse out C++ constructs as well while still in C
> mode, or is it better to be more pedantic and allow for C code which would
> otherwise clash with a C++ compiler (such as using C++ keywords as
> identifiers, ...)?... (IOW, should C++ syntax features be disabled in the
> parser in C mode?...).

If your compiler has a mode in which it's supposed to be a fulling
conforming C compiler, then in that mode your compiler must diagnose any
C++ feature that violates C's syntax rules or constraints. However,
after issuing the required diagnostic messages, it is then free to
implement those C++ features as extensions.

In particular, as soon as the code #includes a C++ standard header, it
is no longer a strictly conforming C program, and your compiler can do
whatever it wants to do with the code, while still being a fully
conforming C compiler.

However, when it runs into strictly conforming C code that would violate
C++ rules or have a different meaning in C++, it must accept that code
(though it's allowed to issue a diagnostic) and it must translate that
code according to C rules. In particular:

> void this()

It cannot reject this code because of this use of 'this',

> {
> int dynamic_cast;

nor because of this use of 'dynamic_cast'.

> int string;

This use of 'string', on the other hand, is perfectly acceptable in both
C and C++. In C++, the block scope definition of 'string' would simply
hide the definition of std::string that might have been introduced by a
preceding #include <iostream> statement.

> ...
> if(dynamic_cast<string>3)

It must parse this as (dynamic_cast < string) > 3, an expression
guaranteed to have a value of 0, regardless of the values of
'dynamic_cast' and 'string'.

> ...
> ...
> }
>
> where relevant, I have allowed some C++-like features to be used in C mode
> via renaming the keywords, such as:
> __namespace {
> __using ...;
> __class Foo {

That's perfectly acceptable: the use of reserved identifiers by such
code renders the behavior undefined, giving your compiler the freedom it
needs to do just about anything you want it to do with such code.


> ...
> };
> ...
> }
>
> but granted this is ugly, and I am not certain if it is really necessary, or
> if one can be more flexible and assume that in their good graces programmers
> will not step needlessly on C++ syntax?...

It's not so much about the programmers as it is about the standards for
the two languages. Something of that kind is necessary if you wish to
support some C++ features while remaining fully conforming to C. In my
opinion, the best way to control it would be with #pragma.

It's not possible to fully conform to both standards. There's code that
is legal in both languages, which is required to have a different
meaning in each - the simplest such example is "sizeof 'a'", which is
required to be the same as sizeof(int) in C, and is required to be 1 in
C++. You can satisfy both requirements, but only if sizeof(int)==1,
which implies CHAR_BITS>=16.

> or, if it would be better to just compile things in "C++" mode, even if the
> implementation is far from complete and probably never will be...

If it will never fully conform to either language's standard, you might
as well do whatever you want to do.

Francis Glassborow

unread,
May 19, 2010, 2:33:08 AM5/19/10
to
James Kuyper wrote:
> BGB / cr88192 wrote:
>> well, here is some thing I am not really sure of.
>>
>> sorry if I missed the relevant sections in the standard...
>>
>>
>> basically, sometimes things may be placed in unusual orders, for example:
>> int * volatile x;
>> but, I am not particularly certain what the semantic difference is from:
>> int volatile *x;
>
> The basic rule is that qualifiers (const and volatile) qualify the thing
> to the right of them. 'int * volatile x' means that 'x', the pointer
> object, is volatile. 'int volatile * x' means that *x, the thing being
> pointed at, is volatile.
>

Did you not mean 'to the left of them'? unless there is nothing to the left

Francis Glassborow

unread,
May 19, 2010, 2:39:12 AM5/19/10
to
James Kuyper wrote:

> It's not possible to fully conform to both standards.

Of course it is, a great deal of C is fully conforming C++. Of course
the reverse is not true..


There's code that
> is legal in both languages, which is required to have a different
> meaning in each - the simplest such example is "sizeof 'a'", which is
> required to be the same as sizeof(int) in C, and is required to be 1 in
> C++. You can satisfy both requirements, but only if sizeof(int)==1,
> which implies CHAR_BITS>=16.

Or you could just not use such code in you C programs then C++ wil have
no problem.

WG21 has made a considerable effort to try to ensure that as much C as
possible is also conforming C++.

Keith Thompson

unread,
May 19, 2010, 3:08:49 AM5/19/10
to
Francis Glassborow <francis.g...@btinternet.com> writes:
> James Kuyper wrote:
>
>> It's not possible to fully conform to both standards.
>
> Of course it is, a great deal of C is fully conforming C++. Of course
> the reverse is not true..

I think the discussion was about a compiler, not code. A compiler
cannot simultaneously conform to both C and C++.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"

James Kuyper

unread,
May 19, 2010, 8:24:34 AM5/19/10
to

No, I meant what I said, though I may be incorrect.

'x' is to the right of 'volatile' in the first declaration, and it is
the expression 'x' that is declared volatile by that declaration. '*x'
is to the right of 'volatile' in the second declaration, and it is the
expression '*x' which is declared volatile by that declaration.

I said "basically", because there's lots of complications. C
declarations were deliberately designed to mirror the usage of the
identifier being declared. My rule applies only those parts of a
declaration that can occur in an expression using the identifier so
declared: *, [], (), etc. It would not apply, for instance, to the 'int'
in 'volatile int x', or the long in 'void f(long)'; those parts should
simply be ignored when using my rule.

Secondly, in many cases the identifier is omitted: as a type argument of
sizeof(), in a cast, or (optionally) in the declaration of a parameter
in a function prototype. In those cases, I apply this rule in terms of a
'ghost' identifier, declared as having the specified type.

I think you're thinking in terms of which type 'volatile' qualifies,
rather than in terms of which expression has the qualified type. That's
perfectly valid, but "to the left of them" doesn't work, at least not
in the general case. It works in the two cases given, where the
volatile-qualified types are 'int*' and 'int', respectively. However,
what about "volatile long x"? I can make my rule work by specifying that
the 'long' should be ignored, but your rule needs the 'long', and the
standard does not impose a strict order on the qualifier relative to the
other specifiers. You'd have to first add some instructions about moving
the qualifier to the right of any such specifiers; and you'd also have
to specify when to stop moving it.

I've long since reached the point in my C career where I'm almost never
confused by a C declaration (unless it's deliberately designed to
confuse - and sometimes not even then). However, I've never attempted
to teach the rules I use for decoding them, so I'm not not had to work
out the details of how to correctly express those rules. One thing I do
know: I've seen other people provide their own descriptions of rules for
understanding declarations, and those rules almost never seem to
correspond to the way I think about them.

James Kuyper

unread,
May 19, 2010, 10:22:54 AM5/19/10
to
Francis Glassborow wrote:
> James Kuyper wrote:
>
>> It's not possible to fully conform to both standards.
>
> Of course it is, a great deal of C is fully conforming C++. Of course
> the reverse is not true..

I was talking about conformance of compilers, not programs. You cannot
write compiler that conforms to both the C and C++ standards when
compiling either of the two modules given below.

A long time ago I was involved in a discussion with someone who claimed
that C functions could not call C++ functions. He had many related
misconceptions. He was under the impression that, in C++, "extern C"
necessarily applies to an entire translation unit. He was completely
unaware of the distinction between the language linkage of an object or
function's name, and the language linkage of a function type. He was
entirely unclear about what he meant by "C function" and "C++ function".
At times he seemed to imply that any function declared as "extern C" in
C++ code was a C function; at other times he seemed to imply that he
considered such functions to be C++ functions, because such a
declaration could only occur in C++ code.

I wrote something like the following program to cover every possibility,
so that no matter how he classified the various functions involved, he
had to consider hidden() to be a C function, and Cppname_Cpptype() to
be a C++ function. Therefore, some where along the calling list between
hidden() and Cppname_Cpptype() there had to be something he would
classify as a C function calling something he would classify as a C++
function.

Later on, I decided it would be a good idea to clarify which functions
were compiled by C rules, and which ones were compiled by C++ rules, by
inserting code which is not a syntax error or a constraint violation in
either language, and which has defined behavior in both languages, but
has different defined behavior in each language. At least, that was my
intention - please let me know if I made any mistakes. I wrote this a
few months ago, and have been waiting for a good excuse for releasing it.

Note: in principle, a fully conforming C90 compiler could react to the
use of __cplusplus in ways that would prevent these modules from
compiling as intended, though in practice this is extremely unlikely. If
using such a compiler, remove the sections controlled by __cplusplus
manually, rather than relying upon the preprocessor to do so.

shared.h:
=======================================================================
#ifndef SHARED_H
#define SHARED_H

extern char tag;
extern int enumer[2];

typedef void voidvoid(void);

int Cnmtyp(void);
int Cfunc(voidvoid*);

#endif
=======================================================================


file1.c:
=======================================================================
#ifdef __cplusplus
extern "C" {
#endif

#include "shared.h"

char tag = 0;

static int hidden(voidvoid *pfunc)
{
(*pfunc)();
tag = sizeof 'C' == sizeof(int);
return Cnmtyp() && enumer[0] && enumer[1];
}

int Cfunc(voidvoid* pfunc)
{
struct tag
{
enum { enumer, other } in;
int integer;
} out;

out.integer = sizeof(tag) == 1 && sizeof(enumer) == sizeof out.in;

return hidden(pfunc) && out.integer;
}

#ifdef __cplusplus
}
#endif
=======================================================================

file2.cpp:
=======================================================================
#ifdef __cplusplus
extern "C" {
#endif

#include "shared.h"

int enumer[2] = {0, 1};

static void Cppname_Cpptype(void)
{
enumer[0] = sizeof 'C' == 1;
return;
}

#ifdef __cplusplus
}
#endif

int Cnmtyp(void)
{
struct tag
{
enum { enumer, other } in;
int integer;
} out;

out.integer = sizeof(enumer) == 2 * sizeof(int);

return out.integer && sizeof(tag) == sizeof out;
}

static voidvoid Cppname_Ctype;

static void Cppname_Ctype(void) {
Cppname_Cpptype();
}

int main(void) {
return Cfunc(&Cppname_Ctype) && tag;
}
=======================================================================

If both modules are compiled by compatible compilers, where the
compilers both conform fully to the same standard, either C90, C99,
C++98, or C++03, then when linked together, the resulting program must
return a failure exist status. On some compilers this might require
using a special option to disable automatic inference of a file's
language from the file name's extension.

However, if file1.c is compiled with a compiler that conforms fully to
either C90 or C99, and file2.cpp is compiled by a compatible compiler
that fully conforms to either C++98 or C++03, then when they are linked
together, the program must return a successful exit status.

Again, those were my intentions, and it works that way in the cases I've
been able to test, but please let me know if I made any mistakes.

This code is more complicated than it needed to be; I needed to define a
number of objects, but in most cases all I needed them for was sizeof
expressions. However, I decided that all of those unused objects looked
bored, so I used them to store intermediate steps in the calculation of
the final result.

This example relies upon two of the most fundamental differences between
C and C++:

The fact that members of each struct type are in a separate scope in
C++, while in C they have the same scope as the struct itself, but are
in a separate name space (both C and C++ have the concept of a 'name
space', which is not at all the same thing as a C++ 'namespace').

The fact that 'struct', 'union' or 'enum' necessarily precedes any use
of a tag in C, but is optional in C++. As a result, C tags can and do
have their own name space, while C++ tags necessarily share the same
name space with ordinary identifiers.

As a result, this code will probably produce the same results even when
using a compiler whose conformance to the relevant standard is rather poor.

BGB / cr88192

unread,
May 19, 2010, 10:36:50 AM5/19/10
to

"James Kuyper" <james...@verizon.net> wrote in message
news:hsvkcb$54m$1...@news.eternal-september.org...

> BGB / cr88192 wrote:
>> well, here is some thing I am not really sure of.
>>
>> sorry if I missed the relevant sections in the standard...
>>
>>
>> basically, sometimes things may be placed in unusual orders, for example:
>> int * volatile x;
>> but, I am not particularly certain what the semantic difference is from:
>> int volatile *x;
>
> The basic rule is that qualifiers (const and volatile) qualify the thing
> to the right of them. 'int * volatile x' means that 'x', the pointer
> object, is volatile. 'int volatile * x' means that *x, the thing being
> pointed at, is volatile.
>
>> my guess is that the former means x is volatile but the pointed-to memory
>> is not, and the latter that the referenced memory is volatile but x is
>> not
>
> Correct.
>
>> ... (or maybe it is the reverse).
>
> Incorrect.
>

fair enough...


>> my compiler though more naively just applies volatile to both, since
>> otherwise likely I would need additional set of flags to differentiate
>> these cases.
>
> If the only thing you do with the incorrectly applied 'volatile' qualifier
> is to turn off optimizations involving the relevant expressions, there's
> no problem.
>
> However, if the incorrectly applied 'volatile' qualifier prevents your
> compiler from generating a mandatory diagnostic, or causes it to reject
> strictly conforming code, then your compiler is non-conforming.
>

yeah, volatile generally is not much of an issue, since all it really means
is turning off caching values in registers...


>> similar applies to const / ..., but for the most part my compiler
>> currently ignores const in most cases.
>
> Ignoring 'const' almost certainly renders your compiler non-conforming.
> While 'volatile' is primarily about optimization, which can always be
> skipped, the primary purpose of 'const' is the diagnostics which become
> mandatory when it is misused. If your compiler doesn't generate them,
> you're doing your users a major disservice.
>

well, the reason for not doing much with const is that I haven't gotten
around much to implement the needed checks in the lower-end...

this is partly because of relatively poor communication between my compiler
upper-end and lower-end on these fronts (mostly due to issues related to my
IL design, which doesn't directly pass flags, but instead types/... are
serialized to signature strings, ...).

granted, it is something I will need to get around to eventually...

but, being lax and allowing something which is otherwise broken, is a much
lesser issue than breaking with things which should work...

basically, it is a long and ongoing effort to patch up all the holes in the
standards conformance, but for the most part the thing works ok... (and a
recent long bout of bug-checking and patching has improved it some, but
mostly this was battling with MSVC and GCC syntax extensions...).


>> also, a mystery:
>> is it "fairly safe" to parse out C++ constructs as well while still in C
>> mode, or is it better to be more pedantic and allow for C code which
>> would otherwise clash with a C++ compiler (such as using C++ keywords as
>> identifiers, ...)?... (IOW, should C++ syntax features be disabled in the
>> parser in C mode?...).
>
> If your compiler has a mode in which it's supposed to be a fulling
> conforming C compiler, then in that mode your compiler must diagnose any
> C++ feature that violates C's syntax rules or constraints. However, after
> issuing the required diagnostic messages, it is then free to implement
> those C++ features as extensions.
>

it has a separate "C mode" and "C++ mode" depending mostly on file-extension
(when used for dynamically-compiled scripts and "eval", it defaults to a
"C-extended" mode, which turns on some features which would otherwise
violate conformance).


> In particular, as soon as the code #includes a C++ standard header, it is
> no longer a strictly conforming C program, and your compiler can do
> whatever it wants to do with the code, while still being a fully
> conforming C compiler.
>
> However, when it runs into strictly conforming C code that would violate
> C++ rules or have a different meaning in C++, it must accept that code
> (though it's allowed to issue a diagnostic) and it must translate that
> code according to C rules. In particular:
>
>> void this()
>
> It cannot reject this code because of this use of 'this',
>
>> {
>> int dynamic_cast;
>
> nor because of this use of 'dynamic_cast'.
>
>> int string;
>
> This use of 'string', on the other hand, is perfectly acceptable in both C
> and C++. In C++, the block scope definition of 'string' would simply hide
> the definition of std::string that might have been introduced by a
> preceding #include <iostream> statement.
>

I would have to check this...


>> ...
>> if(dynamic_cast<string>3)
>
> It must parse this as (dynamic_cast < string) > 3, an expression
> guaranteed to have a value of 0, regardless of the values of
> 'dynamic_cast' and 'string'.
>

fair enough...


>> ...
>> ...
>> }
>>
>> where relevant, I have allowed some C++-like features to be used in C
>> mode via renaming the keywords, such as:
>> __namespace {
>> __using ...;
>> __class Foo {
>
> That's perfectly acceptable: the use of reserved identifiers by such code
> renders the behavior undefined, giving your compiler the freedom it needs
> to do just about anything you want it to do with such code.
>

yep.


>
>> ...
>> };
>> ...
>> }
>>
>> but granted this is ugly, and I am not certain if it is really necessary,
>> or if one can be more flexible and assume that in their good graces
>> programmers will not step needlessly on C++ syntax?...
>
> It's not so much about the programmers as it is about the standards for
> the two languages. Something of that kind is necessary if you wish to
> support some C++ features while remaining fully conforming to C. In my
> opinion, the best way to control it would be with #pragma.
>
> It's not possible to fully conform to both standards. There's code that is
> legal in both languages, which is required to have a different meaning in
> each - the simplest such example is "sizeof 'a'", which is required to be
> the same as sizeof(int) in C, and is required to be 1 in C++. You can
> satisfy both requirements, but only if sizeof(int)==1, which implies
> CHAR_BITS>=16.
>

yep, fair enough...

I already have some special funkiness to enable a "no headers" extension,
which is disabled by default as it is likely to do bad things to code which
otherwise tries to use headers (basically, it makes all
declarations/types/macros/... that the implementation knows about visible at
the same time... which is intended mostly for use in scripts, where
including headers causes the compiler to take much longer...).


>> or, if it would be better to just compile things in "C++" mode, even if
>> the implementation is far from complete and probably never will be...
>
> If it will never fully conform to either language's standard, you might as
> well do whatever you want to do.

well, there may be reasons to try for conformance as much as possible, even
if complete conformance may not be reached...

if, say, 95% of code works without issue, that is better than, say, only 20%
or 30% working...

it is much more about tradeoffs than about "all or nothing"...

all or nothing is rarely useful, but "works most of the time" is typically
fairly useful...

for example: Windows works most of the time, even though it is far from
being 100% reliable...
under an "all or nothing" mindset, Windows couldn't be used since the
occasional bluescreen is inescapable...


sometimes one may be left with code which only works given the good graces
of the result of a random number generator, but misbehavior of the RNG could
render the code non-functional...

however, statistically the code may work without issue...


BGB / cr88192

unread,
May 19, 2010, 11:11:51 AM5/19/10
to

"Keith Thompson" <ks...@mib.org> wrote in message
news:lnpr0s9...@nuthaus.mib.org...

> Francis Glassborow <francis.g...@btinternet.com> writes:
>> James Kuyper wrote:
>>
>>> It's not possible to fully conform to both standards.
>>
>> Of course it is, a great deal of C is fully conforming C++. Of course
>> the reverse is not true..
>
> I think the discussion was about a compiler, not code. A compiler
> cannot simultaneously conform to both C and C++.
>

worse yet if one considers C# and Java syntax, which are also handled by the
same compiler, however I did fork them into a separate parser, since trying
to support both language groups in the same parser (by conditionally
enabling and disabling things) was proving a bit problematic...

the biggie issue is that both language groups handle declarations somewhat
differently, even though the syntax is aesthetically similar...


after forking the parser, I was able to get parsing for both languages
working following some significant alteration...

however, there is some notable overlap, and it is possible to exploit
features in one language which, FWIW, shouldn't actually exist: for example,
using preprocessor commands in Java, or "#include" in C#, ...


however, via conditional enabling/disabling, its is fairly difficult to
avoid some level of syntactic bleed-over between one language and another...


C, C++, Java, and C# all within the same parser was terrible...

now, it is a parser for C and C++ (with a lot of lingering Java & C# cruft
still floating around);
and a parser for Java & C#, with some amount of C cruft floating around...

however, then I am still left thinking there is a lot of redundant code, and
needless redundancy is not ideal.
several major parts could be re-merged, except that there are some
token-level differences between the languages (handling this entirely
generally likely to impose performance costs).

so, it is a tradeoff, namely how much to keep shared, how much separate, and
how to both maintain clenliness and avoid needless redundancy...

if(ctx->lang==BGBCC_LANG_C)
{
...
}else if(ctx->lang==BGBCC_LANG_CPP)
{
...
}else if(ctx->lang==BGBCC_LANG_JAVA)
{
...
}else ...

this sort of thing is ugly...


similarly, I may have reason to add support for an ECMAScript variant of
mine to this compiler, where this ES variant is currently handled by a
different parser and compiler upper-end, but adding ECMAScript syntax to an
already ugly parser is not so ideal either...

(if added, it would likely go to a subset of the Java branch, since this ES
variant has the most syntactic overlap with Java...).


but, oh well, the vast majority of my parser is a big mess of if/else chains
and recursion, so oh well...


Fred Bloggs

unread,
May 19, 2010, 5:09:46 PM5/19/10
to
Francis Glassborow <francis.g...@btinternet.com> wrote in news:I-
mdndb8uJ8JGm7Wn...@bt.com:

Why bother. C++ is bloated. If I want the features of C++ then I should use
C++. If I want a small compact and efficient language then I use C.
C will be getting to the point that one may as well use C++! C will then
die.

0 new messages