Author Topic: The Imperium programming language - IPL  (Read 86848 times)

0 Members and 4 Guests are viewing this topic.

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1772
  • Country: se
Re: A microcontroller programming language
« Reply #300 on: December 01, 2022, 01:17:20 pm »
easily infer that cast itself
That's not a cast.
Nandemo wa shiranai wa yo, shitteru koto dake.
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #301 on: December 01, 2022, 01:23:24 pm »
easily infer that cast itself
That's not a cast.

Very well but it is regularly referred to by that term, and it could be inferred, the compiler has access to enough information to make the inference.

« Last Edit: December 01, 2022, 01:46:50 pm by Sherlock Holmes »
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8888
  • Country: fi
Re: A microcontroller programming language
« Reply #302 on: December 01, 2022, 03:50:07 pm »
Very well but it is regularly referred to by that term, and it could be inferred, the compiler has access to enough information to make the inference.

Compiler could have that information, yes - but this is one of the fundamental rules of C: in assignments, right side is evaluated on its own, with no information fed-forward from the left side.

This again makes the language rules simpler and more predictable.

The same confusion arises when doing arithmetics with different types:
uint32_t a;
uint32_t b;
uint64_t c;

c = a + b;

Per language rules, the result of (a+b) will be of type uint32_t, and only during the assignment is converted to uint64_t. So if a and b are near the limit or numerical range, the result will wrap around; maybe the programmer's intent was:
c = (uint64_t)a + (uint64_t)b;

Maybe a more "clever" language, where the type of destination of assignment was considered, would be good? It would remove one footgun. On the other hand, it would create more subtle ones, as the rules of conversions would get even more complicated than they already are. With current solution, you at least quickly learn the rule - right side is in isolation - and can control the necessary conversions yourself.

In fact, we can go further - if you want such automation, why stop there? Why not remove all the manual type hassle completely? Python does that, and infers the type automagically for you. Some like it, some do not; but clearly the use cases are different. Those who work with microcontrollers, often need the control.
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #303 on: December 01, 2022, 04:56:29 pm »
Very well but it is regularly referred to by that term, and it could be inferred, the compiler has access to enough information to make the inference.

Compiler could have that information, yes - but this is one of the fundamental rules of C: in assignments, right side is evaluated on its own, with no information fed-forward from the left side.

This again makes the language rules simpler and more predictable.

The same confusion arises when doing arithmetics with different types:
uint32_t a;
uint32_t b;
uint64_t c;

c = a + b;

Per language rules, the result of (a+b) will be of type uint32_t, and only during the assignment is converted to uint64_t. So if a and b are near the limit or numerical range, the result will wrap around; maybe the programmer's intent was:
c = (uint64_t)a + (uint64_t)b;

Maybe a more "clever" language, where the type of destination of assignment was considered, would be good? It would remove one footgun. On the other hand, it would create more subtle ones, as the rules of conversions would get even more complicated than they already are. With current solution, you at least quickly learn the rule - right side is in isolation - and can control the necessary conversions yourself.

In fact, we can go further - if you want such automation, why stop there? Why not remove all the manual type hassle completely? Python does that, and infers the type automagically for you. Some like it, some do not; but clearly the use cases are different. Those who work with microcontrollers, often need the control.

This all reduces to how the language determines the type of an expression. I accept that, it's reasonable as is the arithmetic example you cite. The resultant type of expressions is indeed in most languages, deterministically inferred by the types of the operands and the nature of the operators - all good.

And yes some languages can implicitly convert the resultant expression's type to the target's type and some will not.

But here we are dealing with something else, I mean I can write this in C:

Code: [Select]

int ZZZ = 123456;
char MMM;

        MMM = ZZZ;


The compiler does not object and insist I do this:

Code: [Select]

int ZZZ = 123456;
char MMM;

        MMM = (char)ZZZ;


So it's rather idiosyncratic (there's that word again) of C to insist we code:

Code: [Select]

MyType datum;

datum = (MyType){0};


Unless I'm mistaken, this not a case of potential ambiguity, it seems that unless one does (MyType){0} then it will not compile, nothing else is permitted so it could only ever be interpreted that one way.

Look at every example in real code, you'll never find an example of:

Code: [Select]

SomeType A;

A = (SomeOtherType){0};


At least I don't imagine you ever will, I might be wrong though...






« Last Edit: December 01, 2022, 05:03:16 pm by Sherlock Holmes »
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8888
  • Country: fi
Re: A microcontroller programming language
« Reply #304 on: December 01, 2022, 05:48:07 pm »

Code: [Select]

int ZZZ = 123456;
char MMM;

        MMM = ZZZ;


The compiler does not object and insist I do this:

Because compiler knows ZZZ is of type int! Hence, ZZZ can be used as right-side operator in assigments, it can be used in comparisons, arithmetics - wherever.

But you can't write

datum = {0};

only because the language has no idea how to interpret {0}. At lowest level, how many bytes does {0} consist of? No idea, without the type. Compared to that, 0 is treated as int internally. But there is no such default interpretation for {0} (what would it be?), so you need to specify the type (with the cast-like syntax).

Quote
Look at every example in real code, you'll never find an example of:

Code: [Select]

SomeType A;

A = (SomeOtherType){0};


You won't find such example, because it won't compile, because that assignment is invalid as there is no implicit conversion available for the assignment. Yes, C is more strongly typed than you might think!

Code: [Select]
typedef struct { int a; } type1_t;
typedef struct { char b; } type2_t;

int main()
{
        type1_t t1;

        t1 = (type1_t){0}; // OK
        t1 = (type2_t){0}; // error

        return 0;
}

hrst@jorma:~$ gcc t2.c
t2.c: In function ‘main’:
t2.c:10:7: error: incompatible types when assigning to type ‘type1_t’ {aka ‘struct <anonymous>’} from type ‘type2_t’ {aka ‘struct <anonymous>’}
   10 |  t1 = (type2_t){0};


This is why you need to decide how to convert between those types, and create a conversion function, like:

Code: [Select]
twotypes.h

typedef struct {uint32_t thing} thing_wide_t;    // high numerical range thing
typedef struct {uint16_t thing} thing_narrow_t; // low-cost version of thing, same accuracy, less range

static inline thing_narrow_t wide_to_narrow(thing_wide_t in)
{
    thing_narrow_t ret;
    ret.thing = (in.thing > UINT16_MAX):UINT16_MAX:in.thing; // saturate instead of overflow
    return ret;
}


Built-in integer types, for example, have built-in conversions.
« Last Edit: December 01, 2022, 05:49:59 pm by Siwastaja »
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #305 on: December 01, 2022, 07:09:05 pm »

Code: [Select]

int ZZZ = 123456;
char MMM;

        MMM = ZZZ;


The compiler does not object and insist I do this:

Because compiler knows ZZZ is of type int! Hence, ZZZ can be used as right-side operator in assigments, it can be used in comparisons, arithmetics - wherever.

But you can't write

datum = {0};

only because the language has no idea how to interpret {0}. At lowest level, how many bytes does {0} consist of? No idea, without the type. Compared to that, 0 is treated as int internally. But there is no such default interpretation for {0} (what would it be?), so you need to specify the type (with the cast-like syntax).

Quote
Look at every example in real code, you'll never find an example of:

Code: [Select]

SomeType A;

A = (SomeOtherType){0};


You won't find such example, because it won't compile, because that assignment is invalid as there is no implicit conversion available for the assignment. Yes, C is more strongly typed than you might think!

Code: [Select]
typedef struct { int a; } type1_t;
typedef struct { char b; } type2_t;

int main()
{
        type1_t t1;

        t1 = (type1_t){0}; // OK
        t1 = (type2_t){0}; // error

        return 0;
}

hrst@jorma:~$ gcc t2.c
t2.c: In function ‘main’:
t2.c:10:7: error: incompatible types when assigning to type ‘type1_t’ {aka ‘struct <anonymous>’} from type ‘type2_t’ {aka ‘struct <anonymous>’}
   10 |  t1 = (type2_t){0};


This is why you need to decide how to convert between those types, and create a conversion function, like:

Code: [Select]
twotypes.h

typedef struct {uint32_t thing} thing_wide_t;    // high numerical range thing
typedef struct {uint16_t thing} thing_narrow_t; // low-cost version of thing, same accuracy, less range

static inline thing_narrow_t wide_to_narrow(thing_wide_t in)
{
    thing_narrow_t ret;
    ret.thing = (in.thing > UINT16_MAX):UINT16_MAX:in.thing; // saturate instead of overflow
    return ret;
}


Built-in integer types, for example, have built-in conversions.


Yes it knows the type, I understand that. It can also unambiguously infer the type for (Type){0} because it can only ever be one type! this is a good example of a language weakness, if they changed the language to do that type inference (in this specific circumstance) nothing would or could break.

But what you said earlier appears to be incorrect, even in the declaration the RHS has an unknown type!

Code: [Select]

DataStructure datum = {0};


In that snippet, it must be examining the type of datum in order to know what {0} means! So there's no good reason why that same process can't be followed in the later, assignment case.

Code: [Select]

MyStructure a = {0};
MyStructure b;

b = {0};

As a compiler writer, I'm having a hard time understanding the difficulty, surely there's more to all this?

Anyway it is what it is, I'm just less forgiving than you, I have higher, yet reasonable expectations of a serious programming language.

« Last Edit: December 01, 2022, 07:12:54 pm by Sherlock Holmes »
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline SiliconWizard

  • Super Contributor
  • ***
  • Posts: 15439
  • Country: fr
Re: A microcontroller programming language
« Reply #306 on: December 01, 2022, 08:45:14 pm »
Code: [Select]

MyStructure a = {0};
MyStructure b;

b = {0};

As a compiler writer, I'm having a hard time understanding the difficulty, surely there's more to all this?

In C, a literal constructed with curly brackets has no definite type, and its type can't be derived from the literal itself. What is '{0}'? Are you able to give it a type? Nope.
What is '{1,2,3}'? Not any better. Could be an array (of what), could be a struct (with what members?)

For historical reasons, C accepts such *initializers* for practical purposes. In this context, this in an initializer, not a literal that has semantic by itself.

In C99, they introduced compound literals. But you have to give them a type, otherwise they have none. For backwards compatibility, C99 still accepts initializers which are not fully-formed (so, given a type) compound literals. But it doesn't in the context of an assignment, because in this context, the literal has no type and is thus not an expression you can use (again apart from the context of initialization.)

This is all a semantic question. Sure a compiler could 'guess' the type of a compound literal without explicitely giving it a type in the context of an assignment, but it wouldn't fit in the C language with its promotion and implicit conversion rules.

Fact is, defining a syntax with which 'complex' literals (so beyond base scalar types) fully embed their own type is hard. Depending on the "strength" of your type system, it may or may not matter. For a weakly-type language, or even a dynamically-typed language, it may not matter at all. Also depends on what kind of grammar you define and how context-dependent it is.

So can the above proposal you made be implemented? Of course. Are there "corner cases" for which it could be less trivial? Probably.
If you find that useful, why not. But I have enough gripes about all the implicit conversions in C which allow pretty sloppy programming, so I'm not sure I'd want to add a layer of that with "typeless" compound literals.

 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #307 on: December 01, 2022, 09:20:05 pm »
Code: [Select]

MyStructure a = {0};
MyStructure b;

b = {0};

As a compiler writer, I'm having a hard time understanding the difficulty, surely there's more to all this?

In C, a literal constructed with curly brackets has no definite type, and its type can't be derived from the literal itself. What is '{0}'? Are you able to give it a type? Nope.
What is '{1,2,3}'? Not any better. Could be an array (of what), could be a struct (with what members?)

For historical reasons, C accepts such *initializers* for practical purposes. In this context, this in an initializer, not a literal that has semantic by itself.

In C99, they introduced compound literals. But you have to give them a type, otherwise they have none. For backwards compatibility, C99 still accepts initializers which are not fully-formed (so, given a type) compound literals. But it doesn't in the context of an assignment, because in this context, the literal has no type and is thus not an expression you can use (again apart from the context of initialization.)

This is all a semantic question. Sure a compiler could 'guess' the type of a compound literal without explicitely giving it a type in the context of an assignment, but it wouldn't fit in the C language with its promotion and implicit conversion rules.

Fact is, defining a syntax with which 'complex' literals (so beyond base scalar types) fully embed their own type is hard. Depending on the "strength" of your type system, it may or may not matter. For a weakly-type language, or even a dynamically-typed language, it may not matter at all. Also depends on what kind of grammar you define and how context-dependent it is.

So can the above proposal you made be implemented? Of course. Are there "corner cases" for which it could be less trivial? Probably.
If you find that useful, why not. But I have enough gripes about all the implicit conversions in C which allow pretty sloppy programming, so I'm not sure I'd want to add a layer of that with "typeless" compound literals.

I was simply pointing out in my last post the question you ask "What is '{0}'? Are you able to give it a type? Nope." applies in this case too surely, where the expression also appears alone on the RHS of an assignment:

Code: [Select]

MyStructure a = {0};


The compiler knows no more or no less in that case than it does here:

Code: [Select]

MyStructure a;

a = {0};


In both cases, whatever it is able to "know" about "a" must be exactly the same, the only way in can "know" the type in the first example is by looking at the type of "a". I'm not proposing it do that, it's too late, not gonna happen, the language is frankly beyond repair s far as I can see, there seems to be no good design reason for this, it look like laziness or perhaps fragility to existing compiler implementations, I really can't make sense of it.

The question came up due to a different issue and that is the absence of a simply means of initializing any such type, an operation that initializes every member to a suitable default for the type, zero for arithmetic types, null for pointers and so on.

I'd imagine that I'd implement that as something like:

Code: [Select]

dcl a MyStructure = default();

// code...

a = default();

// for any type.


Where default() is a builtin language function. Consider too that setting a pointer "to zero" is not really what the C standard says. It's expected (if my understanding is correct) that when the compiler sees some_pointer = 0; it will - under the hood - set the numeric value to some implementation/target defined value, almost always zero but not quite always. So again there should also be a null() language function or something.

In fact on the Stratus VOS operating system in the past, that did use the numeric value 1, I seem to recall the explanation (I heard on an OS internals class in the late 1980s) that there was some very good hardware basis for this. That system used multiple 68000 (family) processors actually. It was something to do with the fact that 0 is an even number and 1 is odd, and that was important for them.

Here we go: VOS C Language.
« Last Edit: December 01, 2022, 09:41:07 pm by Sherlock Holmes »
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline gf

  • Super Contributor
  • ***
  • Posts: 1353
  • Country: de
Re: A microcontroller programming language
« Reply #308 on: December 02, 2022, 03:25:28 am »
In c++ you can already do that, with slightly different syntax:

Code: [Select]
MyStructure a();
...
a = MyStructure();

And there is also nullptr:

Code: [Select]
some_pointer = nullptr;
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8888
  • Country: fi
Re: A microcontroller programming language
« Reply #309 on: December 02, 2022, 08:16:10 am »
Initialization is indeed exception to the rule. Such is life, rules are arbitrary and not always perfectly logical. That does not mean rules are stupid or useless. I don't mind typing a bit of extra information, when it conveys important information for us programmers, like the type. This adds safety; the C standard requiring me to type the type (pun intended), means:

* I need to keep my brain enabled, less likely to do a mistake with the type
* If I make a mistake and use a wrong type, the compiler will check it for me and error out
* If I want to assign or compare incompatible types, that is only possible by writing the required conversion functions (or doing nasty pointer casting etc., which pokes in the eye)

This is a feature of a strongly typed language. And yet, I would prefer C to be even more strongly typed. Implicit conversions are classic footguns. I don't want any more of them, and oh boy how much I struggled with PHP and its dynamic typing system (although PHP is a disaster in every other regard, too).

Trying to make typing a bit faster is not a valid target. Less than 1% of time in programming is spent actually writing characters on code editor screen.
« Last Edit: December 02, 2022, 08:18:27 am by Siwastaja »
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20768
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: A microcontroller programming language
« Reply #310 on: December 02, 2022, 09:08:42 am »
I don't mind typing a bit of extra information, when it conveys important information for us programmers, like the type. This adds safety; the C standard requiring me to type the type (pun intended), means:

* I need to keep my brain enabled, less likely to do a mistake with the type
* If I make a mistake and use a wrong type, the compiler will check it for me and error out
* If I want to assign or compare incompatible types, that is only possible by writing the required conversion functions (or doing nasty pointer casting etc., which pokes in the eye)

I wish more people saw it like that.

Quote
This is a feature of a strongly typed language. And yet, I would prefer C to be even more strongly typed. Implicit conversions are classic footguns. I don't want any more of them, and oh boy how much I struggled with PHP and its dynamic typing system (although PHP is a disaster in every other regard, too).

I like to point out that in C the variables are strongly typed, whereas the values (i.e. what's out there in the memory) is untyped. That's how you can cast a car to be a camel.

In other languages the variables are untyped whereas the values are strongly typed. Smalltalk is one example. There's no way you can cast a car to be a camel, but you can't predict which it ought to be.

Both approaches have their strengths and weaknesses.

Some languages have both, which - if well conceived - can have the advantages of both. Java is one.

Quote
Trying to make typing a bit faster is not a valid target. Less than 1% of time in programming is spent actually writing characters on code editor screen.

Exactly, in spades. Only beginners and amateurs cannot comprehend that.

If variables are strongly typed then the development environment has a key advantage: you can type ctrl-space (or whatever) and the developer will be presented with a list of what is legal in the context. If there is only one alternative, then it is literally spelled out for the developer. That saves many many keystrokes, and destroys the concept that keystrokes are an issue.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8888
  • Country: fi
Re: A microcontroller programming language
« Reply #311 on: December 02, 2022, 09:21:58 am »
I like to point out that in C the variables are strongly typed, whereas the values (i.e. what's out there in the memory) is untyped. That's how you can cast a car to be a camel.

This weird mix of safety and unsafety is also what makes C powerful and popular: it offers decent level of safety (camel = car is not possible), but also easy enough mechanisms to bypass that safety: camel = *((*camel_t)&car) (or the same via union type punning since C99 or so*). But the latter still - usually! - happens on purpose. Much better than by accident.

*) which is much better, since this "treat memory as the other type" conversion is now documented in the type itself:
typedef union
{
     struct
     {
         int n_humps; // usual camel things
     };
     car_t camel_as_car;
} camel_t;


There are and always will be three classes of people:
* Those who think C is too unsafe and too weakly typed, and should not allow bypassing type safety with any syntax,
* Those who think C is too tedious to work with with all that type bullshit ("come on, I don't want to type, why can't compiler do it for me?")
* Those who are relatively satisfied with the compromise.

It's worth understanding the first two are actually polar opposite of each other. Sometimes you can see a "C complainer" complain about these two opposite problems in the same post, which makes it look... schizophrenic. Or just that sometimes people just want to complain, without having any idea what they are talking about. (And I'm not referring to anyone particular this time.)
« Last Edit: December 02, 2022, 09:36:52 am by Siwastaja »
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4538
  • Country: nz
Re: A microcontroller programming language
« Reply #312 on: December 02, 2022, 11:12:42 am »
Code: [Select]
// ah crud someone banned the following
// camel = *(camel_t*)&car;
extern camel *car_to_camel(car_t *car);
camel = *(car_to_camel(&car));

Code: [Select]
car_to_camel:
camel_to_car:
camel_to_horse:
horse_to_camel:
horse_to_car:
car_to_horse:
  ret
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #313 on: December 02, 2022, 02:37:19 pm »
In c++ you can already do that, with slightly different syntax:

Code: [Select]
MyStructure a();
...
a = MyStructure();

And there is also nullptr:

Code: [Select]
some_pointer = nullptr;

Well that's certainly an improvement!
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #314 on: December 02, 2022, 02:59:13 pm »
Initialization is indeed exception to the rule. Such is life, rules are arbitrary and not always perfectly logical. That does not mean rules are stupid or useless. I don't mind typing a bit of extra information, when it conveys important information for us programmers, like the type. This adds safety; the C standard requiring me to type the type (pun intended), means:

* I need to keep my brain enabled, less likely to do a mistake with the type
* If I make a mistake and use a wrong type, the compiler will check it for me and error out
* If I want to assign or compare incompatible types, that is only possible by writing the required conversion functions (or doing nasty pointer casting etc., which pokes in the eye)

This is a feature of a strongly typed language. And yet, I would prefer C to be even more strongly typed. Implicit conversions are classic footguns. I don't want any more of them, and oh boy how much I struggled with PHP and its dynamic typing system (although PHP is a disaster in every other regard, too).

Trying to make typing a bit faster is not a valid target. Less than 1% of time in programming is spent actually writing characters on code editor screen.

Well the inability of C to deduce (I use that word intentionally because there is no uncertainty) the type when we assign a value {0} is nothing to do with strong or weak typing. The type of the target is known and fixed, at compile time.

I'm not saying the rules are stupid or useless but at best its idiosyncratic and does make the language look almost like a toy language.

If being explicit about the type is so helpful then why do we not see this on every assignment:

Code: [Select]

int a;
short b;
long c;
char d;

a = (int)100;
b = (short)100;
c = (long)100;
d = (long)100;


But we do not see that in code, and I cannot see how such a practice - if it were imposed - would be anything other than unbearable frankly, what you're describing here is not strong typing, it is better described as training wheels!

It's absolutely appropriate to bring a runtime conversion risk to the developer's attention in cases where there is risk, but in the case of my_structure = {0} there is absolutely no risk (so far as I can see), what mistake could one make in this example?

Anyway as I said it is what it is, C is renowned for having many edge cases, it isn't pretty but it is what it is, if one is committed to using C then one accepts it for what it is and use the best discipline one can, but when considering ideas about new languages these observations are pertinent.


« Last Edit: December 02, 2022, 03:04:24 pm by Sherlock Holmes »
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20768
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: A microcontroller programming language
« Reply #315 on: December 02, 2022, 03:14:42 pm »
I like to point out that in C the variables are strongly typed, whereas the values (i.e. what's out there in the memory) is untyped. That's how you can cast a car to be a camel.

This weird mix of safety and unsafety is also what makes C powerful and popular: it offers decent level of safety (camel = car is not possible), but also easy enough mechanisms to bypass that safety: camel = *((*camel_t)&car) (or the same via union type punning since C99 or so*). But the latter still - usually! - happens on purpose. Much better than by accident.

I don't care when an error is caught, so long as it is caught. However, I prefer errors to be caught during compilation.

Quote
There are and always will be three classes of people:
* Those who think C is too unsafe and too weakly typed, and should not allow bypassing type safety with any syntax,
* Those who think C is too tedious to work with with all that type bullshit ("come on, I don't want to type, why can't compiler do it for me?")
* Those who are relatively satisfied with the compromise.

It's worth understanding the first two are actually polar opposite of each other. Sometimes you can see a "C complainer" complain about these two opposite problems in the same post, which makes it look... schizophrenic. Or just that sometimes people just want to complain, without having any idea what they are talking about. (And I'm not referring to anyone particular this time.)

I think there is an irregular verb adjective lurking there: I am safe, you are trustworthy, they are dangerous. Except I can be trusted not to trust myself.

In a low level language with only small applications and simple small libraries, it isn't too difficult to contain the dangers inherent in C.

As applications become larger and more complex, and there are many poorly-understood libraries, my preference to to catch as many type errors during compilation, and to allow casting but verify safety at runtime. That isn't C, of course. It doesn't mean C is wrong, just that there are better languages for large complex applications.

It is not acceptable to advocate minimising typing at the expense of not indicating/documenting intent. The time spent typing is trivial.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: cfbsoftware

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #316 on: December 02, 2022, 03:45:56 pm »
Anyway, I've been immersed in the lexical area once more, I now realize that this is more important than I initially assumed, yes its important but I never really thought about revisiting the entire subject area and taking a fresh look at things.

Here are the kinds of literals that I think one could commit to in a new language:

Code: [Select]

// fixed point decimal literals

1               
11             
101010       
010101       
100 000       
100_000     
256:D         
123.45         

// fixed point binary literals

1:B           
101.101:B   
001 110 010:B
101 110.110:b
110_001:B
11 01101 01.1:B

// fixed point hexadecimal literals 

E:H
17FA:H
0AC0 7F4A:H
1AC0_7F4A:h
4AC6.7C3:H

// Octal literals (no justification/use case for octal fractions...?)

274:O
11 223 752:O
11_223_752:O

// floating point hex literals - 'p' (or 'P') eliminates the need for base designator

123.FE6p+3
123 334.FE6P-3
E05_22B.02p2

// floating point binary literals - 'b' (or 'B') eliminates the need for base designator

110.00101b+4
110.00101b3
1.0101101b-2


So here the (fixed point) base designator (which can be upper/lower case) is moved to the right end of the token, the last component, no need for the 0x prefix any more. No base designator is the same as having the decimal designator. Separators after a decimal point are not permitted (seem to serve no useful purpose IMHO). This is primarily based on a review of the (pretty broad) subject and looking at how some other languages notate these things.

Without the presence of an exponent indicator, fixed point is inferred.












« Last Edit: December 02, 2022, 03:54:07 pm by Sherlock Holmes »
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8888
  • Country: fi
Re: A microcontroller programming language
« Reply #317 on: December 02, 2022, 05:07:11 pm »
Well the inability of C to deduce (I use that word intentionally because there is no uncertainty) the type when we assign a value {0} is nothing to do with strong or weak typing. The type of the target is known and fixed, at compile time.

Sure is, but target is target! It's different thing! Did you not realize you can assign variables of different types to each other if they are compatible and have conversions? For example, uint32_t can be assigned into uint8_t, because narrowing conversion exists.

Quote
If being explicit about the type is so helpful then why do we not see this on every assignment:

The problem with yourself is, because you don't read, you never learn. I already mentioned that 0 is int, this is in language specification, but you ignored this and wasted our time to provide the stupid pseudo example I wanted to avoid by mentioning this early on.

This is why you don't need to specify the type of the literal 100, it's int by default. You can however modify the type, for example 100ULL is unsigned long long int. And you can assign int into float with built-in conversion, so you can write float a = 100. Isn't C fancy?

But what would {0} be? Would it be {int}, or maybe {int, int}, or how about {int, int, int}? Tell me. (And no, "same type as target of assignment" is not the answer.)

So C has already rules how to interpret literals, and how to convert between types. But it has no rule how to interpret more complex compound literals based on some other nearby code.
« Last Edit: December 02, 2022, 05:10:28 pm by Siwastaja »
 
The following users thanked this post: newbrain

Offline Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11713
  • Country: my
  • reassessing directives...
Re: A microcontroller programming language
« Reply #318 on: December 02, 2022, 05:40:14 pm »
Quote
If being explicit about the type is so helpful then why do we not see this on every assignment:
The problem with yourself is...
this is going to be a looong thread :popcorn:
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8888
  • Country: fi
Re: A microcontroller programming language
« Reply #319 on: December 02, 2022, 05:49:32 pm »
Quote
If being explicit about the type is so helpful then why do we not see this on every assignment:
The problem with yourself is...
this is going to be a looong thread :popcorn:

Likely not, I don't usually play these games for too long, it's getting near to the point of getting nothing out of it.
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #320 on: December 02, 2022, 05:53:46 pm »
Well the inability of C to deduce (I use that word intentionally because there is no uncertainty) the type when we assign a value {0} is nothing to do with strong or weak typing. The type of the target is known and fixed, at compile time.

Sure is, but target is target! It's different thing! Did you not realize you can assign variables of different types to each other if they are compatible and have conversions? For example, uint32_t can be assigned into uint8_t, because narrowing conversion exists.

Quote
If being explicit about the type is so helpful then why do we not see this on every assignment:

The problem with yourself is, because you don't read, you never learn.

Please, can you not disagree without being condescending? disparaging?

I already mentioned that 0 is int, this is in language specification, but you ignored this and wasted our time to provide the stupid pseudo example I wanted to avoid by mentioning this early on.

This is why you don't need to specify the type of the literal 100, it's int by default. You can however modify the type, for example 100ULL is unsigned long long int. And you can assign int into float with built-in conversion, so you can write float a = 100. Isn't C fancy?

I think it might actually be you who overlooked something, not I. One can write:

Code: [Select]

char number;

number = 100; // no need to prefix with (char)...an implicit conversion will be inserted.


So what is it? is the 100 a char or an int? Yes, it IS an int and it is being assigned to a char without a (char) on the basis of your earlier argument about "safety" and "footguns" I must assume that you always insert the (char) in such cases, if not why not?

But what would {0} be? Would it be {int}, or maybe {int, int}, or how about {int, int, int}? Tell me. (And no, "same type as target of assignment" is not the answer.)

It could have been whatever the lvalue's type is, or empty braces could have been reserved for just such a use.

So C has already rules how to interpret literals, and how to convert between types. But it has no rule how to interpret more complex compound literals based on some other nearby code.

“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #321 on: December 02, 2022, 06:00:28 pm »
Much of what I say on this thread is simply my personal view on programming languages strengths and weaknesses.

Of course some will agree or disagree on this or that point, disagreement is absolutely a natural part of such conversation, I might be right, I might be wrong or it may be just a difference of opinion.

But there is nothing to be gained by elevating a disagreement a difference of opinion, to the level of personally disparaging remarks about one another.

Time, life is far too fleeting to be wasted in a state of angst, especially over such a relatively unimportant subject in the grand scheme of the universe.



« Last Edit: December 02, 2022, 06:02:44 pm by Sherlock Holmes »
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 20768
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: A microcontroller programming language
« Reply #322 on: December 02, 2022, 06:31:36 pm »
If being explicit about the type is so helpful then why do we not see this on every assignment:

The problem with yourself is, because you don't read, you never learn.

Yes, everything does indicate that.

Now there's nothing wrong with not having read everything; we all start out as beginners. Nor is there anything wrong with going through some of the same thought processes as people have done in the past.

But not knowing the literature, not bothering to read things people suggest would advance his understanding and thinking, and still expecting other people to "discuss" and "explain" things is bad form.

Likely not, I don't usually play these games for too long, it's getting near to the point of getting nothing out of it.

I, and some others, decided that a while ago. The only reason I bother to look at this thread is that some of the peripheral things mentioned by other people are interesting.

But, hey, go knock yourself out :)
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 
The following users thanked this post: cfbsoftware

Offline Siwastaja

  • Super Contributor
  • ***
  • Posts: 8888
  • Country: fi
Re: A microcontroller programming language
« Reply #323 on: December 02, 2022, 07:14:23 pm »
So what is it? is the 100 a char or an int? Yes, it IS an int and it is being assigned to a char without a (char) on the basis of your earlier argument about "safety" and "footguns" I must assume that you always insert the (char) in such cases, if not why not?

That's actually a good question. Yes, sometimes I write explicit cast, sometimes not. The reason not to is when it is obvious what is going to happen anyway (I assume the reader knows the basics of the C standard, but don't assume they know every detail by heart). Such case is assigning uint8_t to uint32_t: it is obvious that the input range [0..255] maps to output range [0..255] and extra bits get filled with zeroes.

On the other hand, maybe I want to emphasize the fact extra bits are generated. Not to compiler, but human reader. Then why not add the explicit cast.

Or, when I convert a float to integer, let's say:
double asdf = 123.4;
int val = asdf + 0.5; // round up and truncate after decimal point

One can emphasize the conversion by writing:
int val = (int)(asdf + 0.5);

But, you can just write
int val = asdf + 0.5;

because the implicit conversion does the same.

But explicit makes sense, because the same thing could be used in a more complex expression, where adding the cast does make the difference:
double something_else = (double)(int)(asdf+0.5) * qwerty;

Remember, programming is not only about making compiler happy, but to convey the meaning to human readers, too.
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #324 on: December 02, 2022, 07:15:08 pm »
If being explicit about the type is so helpful then why do we not see this on every assignment:

The problem with yourself is, because you don't read, you never learn.

Yes, everything does indicate that.

Now there's nothing wrong with not having read everything; we all start out as beginners. Nor is there anything wrong with going through some of the same thought processes as people have done in the past.

But not knowing the literature, not bothering to read things people suggest would advance his understanding and thinking, and still expecting other people to "discuss" and "explain" things is bad form.

Likely not, I don't usually play these games for too long, it's getting near to the point of getting nothing out of it.

I, and some others, decided that a while ago. The only reason I bother to look at this thread is that some of the peripheral things mentioned by other people are interesting.

But, hey, go knock yourself out :)

What exactly have I written that you regard as untrue? If you disagree with something I said then simply quote what I wrote and present your case without making disparaging insinuations. Trying to change the subject from programming language design to me does not help make any kind of logical case about language theory. Attacking the person, their presumed shortcomings does nothing to strengthen any position you might have, arguing emotionally won't  get you anywhere.

Seriously, I expected a higher standard intellectual of rigor in an engineering oriented forum.
“When you have eliminated all which is impossible, then whatever remains, however improbable, must be the truth.” ~ Arthur Conan Doyle, The Case-Book of Sherlock Holmes
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf