How would you design C's replacement?

J

jacob navia

Le 30/04/12 23:04, Ben Pfaff a écrit :
jacob navia said:
Le 30/04/12 20:25, (e-mail address removed) a écrit :

C is perfect?

No language is perfect and so anyone assigning the tasks of
fixing "all [C's] problems and shortcomings" is setting an
impossible goal.

I mentioned specific problems that you snipped.

The fact that perfection is not possible should not be an excuse for
leaving bugs in the language or not trying to improve it.
 
J

Joe keane

If you were given the task to design a replacement for the C
programming language intended to fix all its problems and shortcomings,
what would you propose?

I would make a language where the bitwise operators have higher
precedence than the comparison operators.
 
B

Ben Pfaff

jacob navia said:
Le 30/04/12 23:04, Ben Pfaff a écrit :
jacob navia said:
Le 30/04/12 20:25, (e-mail address removed) a écrit :
If you were given the task to design a replacement for the C programming
language intended to fix all its problems and shortcomings, what would you
propopose?

That the person assigning the task get their head examined. :)

C is perfect?

No language is perfect and so anyone assigning the tasks of
fixing "all [C's] problems and shortcomings" is setting an
impossible goal.

I mentioned specific problems that you snipped.

The fact that perfection is not possible should not be an excuse for
leaving bugs in the language or not trying to improve it.

Jacob, I'm criticizing the hypothetical assignment given by Rui,
not anything you wrote.
 
B

BartC

Rui Maciel said:
These tend to be more subjective than objective. I believe it's more
interesting if we get people to point out what they perceive to be a
problem, why it's a problem and how they would fix it.

OK, let's start with something obvious: C's type-declaration syntax. I find
its inside-out convoluted form completely impossible.

I've often had to resort to CDECL to sort out complex declarations. There
must be something seriously wrong in a language if I have to use external
tools to help understand it! And every time I've discussed this in this
group, I get step-by-step lessons on how to decode, or construct, such a
declaration! Nothing about fixing the language.

Outside of C, I use a type-declaration syntax that reads pretty much like
the English output of CDECL. And I once proposed, in clc, such a
left-to-right syntax for C that could just about co-exist with the old-style
type syntax.

And while we're dealing with the type-system, let's standardise on an
unsigned char type, and have separate signed/unsigned int types of the same
width as char (ie. bytes). There's loads more tidying of the type system
that can be done, but just one more thing for now: I'd also get rid of
struct name-spaces; they're just a source of confusion.
 
K

Keith Thompson

James Kuyper said:
I'm required by our contract with our client to make my application work
simultaneously with four different libraries. Two of them have a number
of typedefs that they use for similar purposes; the other two rely upon
standard C types for those same purposes. My code necessarily reads data
as float64 from the input file, converts to PGSt_double for using
certain utilities, converts to double for using certain C standard
library functions, and then converts back to float64 to write to the
output file. Those are quite likely all the same type - but the library
makers reserve the right to make them different types, depending upon
the platform where my program is compiled, or depending upon the version
of the library. As a result, I can't meet my portability requirements
unless I write my code so it works properly even if float64, PGSt_double
and double turn out to be three different types.
[...]

Out of curiosity, how to you verify that your code would still work if
these were different types? Do you have a test configuration with
modified versions of the libraries?
 
K

Keith Thompson

Rui Maciel said:
I believe it can be argued that the C programming language is already a
"fake assembly language" as it is.

But not persuasively, IMHO.

C is at a lower semantic level than a lot of other languages.
But the major difference between C and assembly language is that
an assembly program specifies CPU instructions, while a C program
specifies run-time behavior.

That's a *huge* distinction, with assembly languages on one side,
and C, C++, Ada, Python, APL, and Intercal firmly on the other.
 
I

Ian Collins

There have been dozens, if not hundreds attempts to create a "better"
language than C. Heck, I've speculated how such a thing might look,
and have a laundry list of things I'd like changed.

The problem is that all this entirely misses the point. C is an OK
low-ish level language, with no horrible flaws that prevent its use in
many places. There *are* dozens of better languages, even for C's
primary system level purpose. C's value has almost nothing to do with
its quality as a language (other than the avoidance of terrible
flaws), and everything to do with its ubiquity.

And if you can't address C's ubiquity, you aren't going to have a
better language than C.

C's ubiquity comes in various forms, not only as run anywhere but also
find a programmer anywhere.

Most of the embedded projects I have been involved with recently use gcc
and a decent subset of those used gcc and a Linux kernel. One of my
first questions I asked on joining those projects was "why don't you use
C++?" and the answer invariably boils down to "we use what we are
familiar with".

So if it's hard to find experienced developers for the most popular C
derived language, I'd hate to be the one promoting a new one!
 
B

BGB

Probably because this newsgroup isn't really about "fixing the
language".

agreed.

I personally see little problem with the syntax in-general, except in a
few cases.

If you wanted to add a new declaration syntax to C, it would have to
*completely* coexist with the existing syntax. Breaking existing code
is not an option. (Yes, each new C standard has broken *some* existing
code, at least theoretically, but breaking every declaration more
complex than "int i;" would not be acceptable.)

And while I agree that a better syntax for a hypothetical new language
(the "C's replacement" we're discussing in this thread) would be great,
I'm not sure that a C-like language supporting both the existing syntax
and a new syntax would be better than one that just supports the
existing syntax.

my own language (BGBScript) has an issue similar to this.


given its ECMAScript heritage, it has ECMAScript-style declarations.
given other reasons (mostly related to inter-language copy/paste), it
also has a more Java/C# style declaration syntax.

it is kind of annoying, as there is an issue as to which syntax is more
canonical.

I am mostly leaning more towards the ES-style being more canonical, more
because the language is technically an ES variant (it is largely
ECMA-262 conformant), and so it makes more sense if the language uses as
its canonical syntax, the one defined in the standard on which it is based.


example:
var x;
var i:int;
var a:int[];
var pv:*void;
vs:
variant x; //(1)
int i;
int[] a;
*void pv; //(2)

1: this syntax is longer and not strictly equivalent to "var x;",
however "var x;" is technically the other syntax given that var is a
declaration keyword. "variant x" is technically equivalent to "var
x:variant;". there is currently little functional difference though.

note that, given how the declaration parser works, it is also
technically possible to create double-typed variables, as in:
"int x:long, y:double;"

however, these currently have little practical use, and should be
considered an error (as-is, the later types will override the base type).

function declaration syntax is also partly redundant:
function foo(x:int):void { ... }
vs:
void foo(int x) { ... }


as-is, closures can only be declared with an ES-like form (sort of),
given that there are syntax problems otherwise.

function(x) { ... }
function(i:int):void { ... }

however:
function(int i) { ... }
function(int i):void { ... }
will probably work...

things like getters/setters, ... also have redundant syntax.

function get x():int { ... }
vs:
int get x() { ... }

....


2: "*type" was used instead of "type*" in my language due to there being
several cases in which the later would be syntactically ambiguous.
although declaring pointers this way may look strange, as-is it is a
fairly trivial change, and doesn't particularly hinder converting C code
to BGBScript, or at least not nearly as much as the differences in the
cast syntax.


a recent set of (fairly fundamental) changes in my interpreter has made
many of these types more canonical, as now declaring a variable as "int"
will actually store the variable as a 32-bit integer internally, rather
than, say, as a fixnum.

these changes have introduced a lot of bugs, so it is still an ongoing
transition.


I was also recently thinking and considering if my interpreter would be
fast enough to allow porting Quake to my Script VM. if some recent
benchmarks are representative, my interpreter is performing comparably
to the sorts of hardware Quake 1 and 2 were developed for, and so should
be sufficiently fast to run these games (even without a JIT).

granted, I would likely need a C front-end for this VM (sadly, doesn't
currently exist, 3), as it would probably be too much effort to port the
entire Quake 1 or Quake 2 engine to BGBScript.

not sure yet if I will actually attempt a thing, since as-is, this would
still be a fairly big project given the present state of the VM.


3: my existing C compiler targeted a different back-end, which is no
longer in operation. I would either need to modify this front-end to
target the current Script VM, or very possibly create a new C front-end,
or possibly a combination (keeping the existing parser, but write a new
AST->bytecode stage).

But something that might be interesting, not as a language change but as
a development tool, would be integrating something like cdecl into the
build process. You could write code in a C-like dialect, with
declarations written in your new syntax, and your build tool would
automatically generate syntactically correct C. Another tool could
translate C declarations into your syntax. It would let you use your
preferred syntax while still being able to share C code with others who
don't have your tools.

it is possible...

I presume you mean requiring plain "char" to be unsigned (we already
have "unsigned char"). I tend to agree; permitting plain char to be
signed causes a lot of conceptual problems. I wonder what kind of
performance problems it might introduce, though; char expressions are
frequently promoted to int, and that promotion might be more expensive
on some systems if plain char is signed. (I presume that's why so many
compilers make plain char signed, when making it unsigned would be
perfectly legal.)

in my language, I split them up, so these types are more like:
byte: 8-bit unsigned byte;
sbyte: 8-bit signed byte;
short: 16-bit signed short;
ushort: 16-bit unsigned short;
char8: 8-bit unsigned char;
char/char16: 16-bit unsigned char.

char is not strictly equivalent to ushort, as they will have slightly
different semantics.
 
K

Kaz Kylheku

OK, let's start with something obvious: C's type-declaration syntax. I find
its inside-out convoluted form completely impossible.

The problem with any major changes to C's type declaration syntax is that
they break "declaration follows use".

A declarator like (*p[3])(double) gives us a p which can actually be used by
means of the syntax (*p[0])(3.0).

If you change how it is declared, but don't make a parallel change to the
expression syntax then you still have (*p[0])(3.0) /and/ the new syntax which
is inconsistent with this.
 
J

James Kuyper

James Kuyper said:
I'm required by our contract with our client to make my application work
simultaneously with four different libraries. Two of them have a number
of typedefs that they use for similar purposes; the other two rely upon
standard C types for those same purposes. My code necessarily reads data
as float64 from the input file, converts to PGSt_double for using
certain utilities, converts to double for using certain C standard
library functions, and then converts back to float64 to write to the
output file. Those are quite likely all the same type - but the library
makers reserve the right to make them different types, depending upon
the platform where my program is compiled, or depending upon the version
of the library. As a result, I can't meet my portability requirements
unless I write my code so it works properly even if float64, PGSt_double
and double turn out to be three different types.
[...]

Out of curiosity, how to you verify that your code would still work if
these were different types? Do you have a test configuration with
modified versions of the libraries?

I can't easily test conformance of my code to it's portability
requirements. We used to have several different platforms I could test
on, now all of our machines are made by the same manufacturer and run
the exact same version of the same operating system. The only variation
is that some of them are 32-bit and some are 64-bit, so I can at least
test that aspect of portability. Having a only a small number of
different machine set-ups simplifies system administration - an
important issue when a couple of system administrators are taking care
of nearly a thousand computers, but it makes portability testing harder.
I rely upon my own knowledge of what needs to be done to ensure
portability, and hope that I've done it right. The only place our code
really needs to run is on those thousand or so computers; that it must
be available to the general scientific community, and therefore highly
portable, is a requirement of our contract, but is substantially less
important.

In principle, if anyone has trouble installing or running my software on
a system different from the ones I've tested the code on, they should
complain to me. If they do, I'd be happy to investigate and try to solve
the problem, but if the issue ever comes up, I'll have to ask them to
give me access to their system to do my debugging.

We're allowed to assume POSIX conformance, and so far the only such
complaint I've received was from someone trying to port our code to a
non-POSIX environment. I was rather annoyed that I couldn't help him;
the linker he was using was failing to link in the right libraries, and
I didn't know enough about that platform to help him figure out why. He
knew more about how his linker worked than I did, and he couldn't figure
it out. I might have been able to figure it out with direct access to
his system, but his IT security people wouldn't allow it.
 
B

BGB

OK, let's start with something obvious: C's type-declaration syntax. I find
its inside-out convoluted form completely impossible.

The problem with any major changes to C's type declaration syntax is that
they break "declaration follows use".

A declarator like (*p[3])(double) gives us a p which can actually be used by
means of the syntax (*p[0])(3.0).

If you change how it is declared, but don't make a parallel change to the
expression syntax then you still have (*p[0])(3.0) /and/ the new syntax which
is inconsistent with this.


to be fair though, something like:
void (*fooptr)(double x);

is usually called using something like:
fooptr(3.0);


and so some change to the function pointer syntax could still be
justifiable, say if people would instead have to write:
typedef void fooptr_t(double x);
fooptr_t *fooptr;

or, OTOH, use some sort of funky QuakeC-style syntax:
void(double x) *fooptr;


this later option would change a declaration from something like:
void (*foo())(int x)
{ ... }
into something like:
void(int x) *foo()
{ ... }


or such...
 
B

BGB

Le 30/04/12 20:25, (e-mail address removed) a écrit :

C is perfect?

Trigraphs included?

Now, come on...

a person could write a spec for a "new language" nearly identical to C,
but absent things like trigraphs and K&R style declarations.


oddly, my C parser already does this.
it supports "most of the language" but omits "parts I don't actually
tend to see used".


granted, I got into arguments with people before as to what dropping K&R
syntax would mean for functions like:
void foo();
which in my case I had simply treated as equivalent to:
void foo(void);

where a person is far more likely to see a "()" function not expecting
any arguments, than they are to see something like:

foo(x, y) int x, y;
{ ... }

which will not actually parse in my case.


but, this was a long and pointless argument...


hmm, partial C subset, could be called "C-Axe", because it "cuts off
some rarely-used features".
 
I

Ian Collins

OK, let's start with something obvious: C's type-declaration syntax. I find
its inside-out convoluted form completely impossible.

I've often had to resort to CDECL to sort out complex declarations. There
must be something seriously wrong in a language if I have to use external
tools to help understand it! And every time I've discussed this in this
group, I get step-by-step lessons on how to decode, or construct, such a
declaration! Nothing about fixing the language.

More often than not there's something wrong with the programmer who
conjurers up such a convoluted declaration! Seriously, 99.9% of the
time complex type declarations are unnecessary.

One simplification that would help not break (much!) code would be to
adopt C++'s reuse of "auto". It would be very handy for those cases
where the compiler knows the type an expression and the programmer
doesn't really care. I have my own C++ Auto object type I use with my
JSON library and I've found it extremely useful in such cases.
 
B

BGB

More often than not there's something wrong with the programmer who
conjurers up such a convoluted declaration! Seriously, 99.9% of the time
complex type declarations are unnecessary.

One simplification that would help not break (much!) code would be to
adopt C++'s reuse of "auto". It would be very handy for those cases
where the compiler knows the type an expression and the programmer
doesn't really care. I have my own C++ Auto object type I use with my
JSON library and I've found it extremely useful in such cases.

yeah, auto would be nice...


placing restrictions on declaration keyword orderings is also possible
and not likely to break all that much code (probably 95% would still
work), and could allow faster parsers (as well as allow eliminating
context dependency), such as by allowing switching to a C#-style parsing
strategy.

there are drawbacks though, namely that not all code or headers would
parse correctly, meaning it would likely involve a compiler option or
similar to enable it.
 
I

Ian Collins

yeah, auto would be nice...


placing restrictions on declaration keyword orderings is also possible
and not likely to break all that much code (probably 95% would still
work), and could allow faster parsers (as well as allow eliminating
context dependency), such as by allowing switching to a C#-style parsing
strategy.

there are drawbacks though, namely that not all code or headers would
parse correctly, meaning it would likely involve a compiler option or
similar to enable it.

Unlike incorporating C++'s "auto" which could be seamless.
 
B

BGB

C's ubiquity comes in various forms, not only as run anywhere but also
find a programmer anywhere.

Most of the embedded projects I have been involved with recently use gcc
and a decent subset of those used gcc and a Linux kernel. One of my
first questions I asked on joining those projects was "why don't you use
C++?" and the answer invariably boils down to "we use what we are
familiar with".

So if it's hard to find experienced developers for the most popular C
derived language, I'd hate to be the one promoting a new one!

I also use mostly C, rather than C++, albeit I have my own reasons.
earlier on, I think it was because G++ was often either broken or buggy
(or, sometimes, missing altogether), so I didn't really trust it.


the most notable issue at present being that writing a C++ parser for my
tools to use looks like a huge PITA, so thus far I haven't really seen
it as a justified effort (more so for sake of features which are,
technically, mostly just syntax sugar anyways).

if I can write "slightly less clean" and do similar in C, it isn't
really a worthwhile tradeoff to use C++.


but, in any case, my language efforts aren't really intended to
"replace" C, as personally I see it as a fairly solid language for what
it does.


so, alas...
 
I

Ian Collins

If you were given the task to design a replacement for the C programming
language intended to fix all its problems and shortcomings, what would you
propopose?

In addition to my other post concerning C++'s auto, there are a number
of other additions to C++11 that would benefit in C without breaking
existing code, some examples

Scoped and strongly typed enums[1], embedded compilers often enable the
type of an enum to be selected, so may as well standardise.

Constant expressions[2] would extend the usefulness of const.

Alignment[3] another extension that may well be of more use in C (giving
its dominance in drivers and embedded).

Narrowing prevention[4]

[1] http://www2.research.att.com/~bs/C++0xFAQ.html#enum
[2] http://www2.research.att.com/~bs/C++0xFAQ.html#constexpr
[3] http://www2.research.att.com/~bs/C++0xFAQ.html#align
[4] http://www2.research.att.com/~bs/C++0xFAQ.html#narrowing
 
B

BGB

Unlike incorporating C++'s "auto" which could be seamless.

pretty much, but they do different things.


auto allows simpler-looking declarations.

alternate declaration parsing allows for a potentially somewhat faster
parser and compiler (combined with other tricks). I am not promoting
here making "obvious syntax changes", rather using a different parsing
strategy (with the restrictions being mostly a side cost).

like, wouldn't it be nice if, say, a person could compile about 100 kloc
of code in, say, 250ms or 500ms or so?... (vs maybe 10-20 seconds, most
due to endlessly re-parsing things like "windows.h" and similar...).

granted, it may be all a bit domain-specific, hence probably why it
would be a command-line option to enable it.


so, either way...
 
I

Ian Collins

I also use mostly C, rather than C++, albeit I have my own reasons.
earlier on, I think it was because G++ was often either broken or buggy
(or, sometimes, missing altogether), so I didn't really trust it.


the most notable issue at present being that writing a C++ parser for my
tools to use looks like a huge PITA, so thus far I haven't really seen
it as a justified effort (more so for sake of features which are,
technically, mostly just syntax sugar anyways).

Full C++ is extremely complex to parse, but the C with classes subset
shouldn't present too many problems (see cfront) and provides a
worthwhile superset of C.
 
K

Keith Thompson

BGB said:
[...]
a few thoughts:

"#include", maybe some sort of alternative mechanism could be devised,
like a standardized precompiled header mechanism.

a major issue is mostly that as-is, if you do:
#include <foo.h>
#include <bar.h>

then by definition declarations within "foo.h" may alter the behavior of
declarations within "bar.h", regardless of whether or not such behavior
is desired or relevant.

a better mechanism could be one which is "similar" to include, except it
leaves the matter undefined as to whether actual textual inclusion is
used, or if the headers are compiled independently (and their contents
imported later).

one idea here:
#pragma pch_standalone
or:
#pragma precompiled_header
[...]

If we're trying to come up with something better than #include, I'd
rather create a new mechanism that isn't part of the preprocess, and
doesn't look like it is (#pragma).

For example, this:

#include <stdio.h>

could be replaced by:

import stdio;

This would make all the declarations in the stdio "module" visible; it
would be up to the implementation to determine how to do that. There's
no implication that "import" performs a textual replacement.

There's plenty of precedent for this kind of thing in other languages.

I don't expect (or, probably, even advocate) that a future C standard
will have such a feature, but it's probably part of my own hypothetical
never-to-be-fully-defined C-like language.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,743
Messages
2,569,478
Members
44,898
Latest member
BlairH7607

Latest Threads

Top