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

0 Members and 8 Guests are viewing this topic.

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: A microcontroller programming language
« Reply #550 on: December 22, 2022, 09:48:37 am »
For example C has no function nesting, representing that - in a general way - in C requires abstracting the concept, this is why a more machine like abstraction might be better, in fact generating assembly language embedded in C might be better then a C dev environment could be used as is.

GNU C has an extension for function nesting.

You don't need to generate nested functions in the C output to implement source language nested functions.

But it would be much easier if the compiler uses the GNU C extension for the nested functions. The nested functions should be able to access the context of the surrounding function(s). Without nesting, accessing the context of the surrounding function(s) may get really difficult to implement.
 

Offline brucehoult

  • Super Contributor
  • ***
  • Posts: 4069
  • Country: nz
Re: A microcontroller programming language
« Reply #551 on: December 22, 2022, 10:56:00 am »
For example C has no function nesting, representing that - in a general way - in C requires abstracting the concept, this is why a more machine like abstraction might be better, in fact generating assembly language embedded in C might be better then a C dev environment could be used as is.

GNU C has an extension for function nesting.

You don't need to generate nested functions in the C output to implement source language nested functions.

But it would be much easier if the compiler uses the GNU C extension for the nested functions. The nested functions should be able to access the context of the surrounding function(s). Without nesting, accessing the context of the surrounding function(s) may get really difficult to implement.

Easier, but maybe you don't like the way that compiler implements it, or you want to be able to use other C compilers too (MSVC, SDCC, whatever...)

And it's not hard at all. For example each function declares a struct type with all its local variables in, then declares just one actual local variable of that type. The address of it can be passed as an extra argument to "nested" functions ("static link"), or stored in a global array ("display").

Or only put the variables that are actually used by the nested function in that struct. Or allocate that struct on the heap not the stack so you have a proper closure, not simply nested functions -- that's a common language feature that you CAN'T implement using gcc nested functions.

This is all completely trivial compared to the rest of the work of writing a compiler.
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: A microcontroller programming language
« Reply #552 on: December 22, 2022, 12:11:10 pm »
For example C has no function nesting, representing that - in a general way - in C requires abstracting the concept, this is why a more machine like abstraction might be better, in fact generating assembly language embedded in C might be better then a C dev environment could be used as is.

GNU C has an extension for function nesting.

You don't need to generate nested functions in the C output to implement source language nested functions.

But it would be much easier if the compiler uses the GNU C extension for the nested functions. The nested functions should be able to access the context of the surrounding function(s). Without nesting, accessing the context of the surrounding function(s) may get really difficult to implement.

Easier, but maybe you don't like the way that compiler implements it, or you want to be able to use other C compilers too (MSVC, SDCC, whatever...)

And it's not hard at all. For example each function declares a struct type with all its local variables in, then declares just one actual local variable of that type. The address of it can be passed as an extra argument to "nested" functions ("static link"), or stored in a global array ("display").

Or only put the variables that are actually used by the nested function in that struct. Or allocate that struct on the heap not the stack so you have a proper closure, not simply nested functions -- that's a common language feature that you CAN'T implement using gcc nested functions.

This is all completely trivial compared to the rest of the work of writing a compiler.

Although the nested functions are handy and helpful, it is possible to create programs without them. Therefore the nested functions should probably be included in the grammar only as new language feature in the future.
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: A microcontroller programming language
« Reply #553 on: December 22, 2022, 12:47:03 pm »
<snip>
memory alignment, field ordering, padding
big/little endian issues
coroutines and cofunctions
exception support
runtime checks
fixed point arithmetic
nested procedures/functions
argument passing
contracts
computed goto
offsets (as opposed to pointers)
array and string metadata
bit data type support
<snip>

in the spirit of C++, any plans for passing an argument of a function as reference, too? That would remove the need of using the dereference-operator when accessing a variable inside the function that was passed as a reference. Passing arguments as a reference will also remove the need for checking NULL pointer values for the arguments.

Talking about the NULL pointers: Please introduce a proper keyword for denoting a NULL pointer value, for example null or nullptr.
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #554 on: December 22, 2022, 12:58:09 pm »
I've managed to get Antlr to recognize the grammar's support for numeric literals in multiple bases and which can contain readability spaces (or underscore) as separators. All of these are recognized:

Code: [Select]
proc test(x)

value = DEF ABC 2DC0 6BA0:h * 100; // note, no more than a single space can be the separator.

call reboot(FACE DEFB 10C0:H + 239:H);

value = 100 123.45;

value = 1011 FC4.7F:h;

value = 1010 1010;

value = 123:d;

value = 1010 1010:b;

octal = 765:o;

end;


There are four kinds of numeric literals, binary, octal, decimal and hex, they all need a colon-char base designator except dec, for which this can be omitted.

Personal opinion: I do not like spaces in the literals. Underscore, for example, would be better.

From the tokenizer/parser point of view things would be much easier if the spaces would not be allowed in literals. See also my comment about the tools below.

Edit: There has also been some discussion on how to group the digits in numerical literals. I guess that it would be possible to build a simple tool using regexpr rule(s) for checking the grouping of the digits for floating point, decimal, hex, octal and binary numbers of person's liking. Just run the checker as part of the build process, and the checker will fail the build process if the numerical literals are using invalid grouping. Building a directive for the rules of digit grouping into the language grammar could be also possible, but I am not sure if that would be a wise choice (without extensive prototyping and evaluation at least).

---

At some point in this thread there was a discussion whether to use reserved words or not. I think the history of the programming languages have shown that using reserved words makes the grammar easier to parse and reduce ambiguity. Just keep the grammar as simple as possible.

About tools: All tools - such as code formatters, IDEs, refactoring tools etc. - would benefit from a simple grammar without ambiguity.

We have something like 70 years of knowledge about programming languages, so there is no need to repeat the problems of the earlier programming languages.

The (single) space is entirely optional and underscore also permitted. There are standards bodies who recommend spaces over commas or periods, the space is actually common in several industries and reduces risk of misunderstanding across cultures, I did research this, its an interesting aspect of language design.

Having the type as suffix (e.g :H) rather than a prefix (e.g. 0x) is what makes these spaces possible, more effort to recognize but Antlr4 is extremely powerful.

The reserved words question gets much attention, the core motive is never ever fail to compile code that might have identifiers that are the same as newly added language keywords. Consider C# where they had to use "yield return" when simply "yield" was the obvious choice, their grammar could not support this and be backward compatible.

That's frankly a poor design right there, but like most languages the designers pay too little attention to careful methodical grammar design, grammar's must be designed, no escaping this point, the trend for years has been "make it C-like" and just look at the problems that's led to.

Of course avoiding, minimizing obfuscation is important too, and providing compile time options to warn against unintended keyword clash is easy to do and better then losing backward compatibility.

I want to stress that the grammar has no ambiguities, C++ even C do have grammar ambiguities, you can read about these, C++ also has the most complex grammar of any programming language, littered with edge cases and ifs and buts, until recently this construct was illegal in C++

Code: [Select]

Typename<Type<Other>>


Instead one was forced to write

Code: [Select]

Typename<Type<Other> >


That's frankly ridiculous (the >> is recognized as a shift operator) and can be traced back to sloppy or hasty grammar choices, I talk about this a lot but that's because its very important, without careful design you get all the syntax mess we see in C++, C# and so on.

This new grammar parses robustly, easily that's because there are only two fundamental kinds of statements, assignments and keyword statements.

An assignment (however complex lexically) can always be recognized 100% reliably irrespective of the spelling of terms. Only if a statement is not an assignment do we look for a keyword start.

Despite first impressions, this is actually simple, not complex, grammars should have this kind of power IMHO.









« Last Edit: December 22, 2022, 01:44:56 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 Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #555 on: December 22, 2022, 01:06:54 pm »
<snip>
memory alignment, field ordering, padding
big/little endian issues
coroutines and cofunctions
exception support
runtime checks
fixed point arithmetic
nested procedures/functions
argument passing
contracts
computed goto
offsets (as opposed to pointers)
array and string metadata
bit data type support
<snip>

in the spirit of C++, any plans for passing an argument of a function as reference, too? That would remove the need of using the dereference-operator when accessing a variable inside the function that was passed as a reference. Passing arguments as a reference will also remove the need for checking NULL pointer values for the arguments.

Talking about the NULL pointers: Please introduce a proper keyword for denoting a NULL pointer value, for example null or nullptr.

Yes, all args are passed by ref. To achieve pass by value (that is, pass a ref to a temp copy) one just surrounds the arg in parens:

Code: [Select]

call set_timer((timer_id));


That makes the arg into an expression and expressions are always evaluated into a temporary and a ref to that temp then passed. No need for & and * all over the place!
« Last Edit: December 22, 2022, 01:34:22 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 Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: A microcontroller programming language
« Reply #556 on: December 22, 2022, 01:40:32 pm »
<snip>
memory alignment, field ordering, padding
big/little endian issues
coroutines and cofunctions
exception support
runtime checks
fixed point arithmetic
nested procedures/functions
argument passing
contracts
computed goto
offsets (as opposed to pointers)
array and string metadata
bit data type support
<snip>

in the spirit of C++, any plans for passing an argument of a function as reference, too? That would remove the need of using the dereference-operator when accessing a variable inside the function that was passed as a reference. Passing arguments as a reference will also remove the need for checking NULL pointer values for the arguments.

Talking about the NULL pointers: Please introduce a proper keyword for denoting a NULL pointer value, for example null or nullptr.

Yes, all args are passed by ref. To achieve pass by value (that is, pass a ref to a temp copy) one just surrounds the arg in parens:

Code: [Select]

call set_timer((timer_id));


That makes the arg into an expression and expressions are always evaluated into a temporary and a ref to that temp then passed. No need for & and * all over the place!

The function declaration should be the place where it is defined whether an argument is passed by value or by reference.
 

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: A microcontroller programming language
« Reply #557 on: December 22, 2022, 02:14:31 pm »
I want to stress that the grammar has no ambiguities, C++ even C do have grammar ambiguities, you can read about these, C++ also has the most complex grammar of any programming language, littered with edge cases and ifs and buts, until recently this construct was illegal in C++

Code: [Select]
Typename<Type<Other>>

Instead one was forced to write

Code: [Select]
Typename<Type<Other> >

That's frankly ridiculous (the >> is recognized as a shift operator) and can be traced back to sloppy or hasty grammar choices, I talk about this a lot but that's because its very important, without careful design you get all the syntax mess we see in C++, C# and so on.

Ada has a major blooper too as they are using parenthesis () for array index instead of brackets []. Now it is impossible to determine whether a(n) is a function call or an array element access, without checking the actual definition.

Crafting a programming language is really hard, and it is very easy to make mistakes that may carry on for decades.
« Last Edit: December 22, 2022, 02:16:23 pm by Kalvin »
 

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #558 on: December 22, 2022, 02:26:51 pm »
<snip>
memory alignment, field ordering, padding
big/little endian issues
coroutines and cofunctions
exception support
runtime checks
fixed point arithmetic
nested procedures/functions
argument passing
contracts
computed goto
offsets (as opposed to pointers)
array and string metadata
bit data type support
<snip>

in the spirit of C++, any plans for passing an argument of a function as reference, too? That would remove the need of using the dereference-operator when accessing a variable inside the function that was passed as a reference. Passing arguments as a reference will also remove the need for checking NULL pointer values for the arguments.

Talking about the NULL pointers: Please introduce a proper keyword for denoting a NULL pointer value, for example null or nullptr.

Yes, all args are passed by ref. To achieve pass by value (that is, pass a ref to a temp copy) one just surrounds the arg in parens:

Code: [Select]

call set_timer((timer_id));


That makes the arg into an expression and expressions are always evaluated into a temporary and a ref to that temp then passed. No need for & and * all over the place!

The function declaration should be the place where it is defined whether an argument is passed by value or by reference.

That's a possibility I agree. But then we must sacrifice the ability to ever pass by ref to some code, just because we might have some scenarios where we don't want the caller to modify the arg.


“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 #559 on: December 22, 2022, 02:32:03 pm »
I want to stress that the grammar has no ambiguities, C++ even C do have grammar ambiguities, you can read about these, C++ also has the most complex grammar of any programming language, littered with edge cases and ifs and buts, until recently this construct was illegal in C++

Code: [Select]
Typename<Type<Other>>

Instead one was forced to write

Code: [Select]
Typename<Type<Other> >

That's frankly ridiculous (the >> is recognized as a shift operator) and can be traced back to sloppy or hasty grammar choices, I talk about this a lot but that's because its very important, without careful design you get all the syntax mess we see in C++, C# and so on.

Ada has a major blooper too as they are using parenthesis () for array index instead of brackets []. Now it is impossible to determine whether a(n) is a function call or an array element access, without checking the actual definition.

Crafting a programming language is really hard, and it is very easy to make mistakes that may carry on for decades.

Well that's an interesting point, PL/I (and my draft grammar) do the same as Ada, I've never thought much about this, like how important is it to be able to differentiate, modern IDE technology could easily render arrays in a different color to functions too. I'll think about this...
“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: 19723
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: A microcontroller programming language
« Reply #560 on: December 22, 2022, 02:48:29 pm »
Talking about the NULL pointers: Please introduce a proper keyword for denoting a NULL pointer value, for example null or nullptr.

Or avoid "the billion dollar mistake" altogether. https://en.wikipedia.org/wiki/Null_pointer#History

That would be far more useful than diddling with syntax.
« Last Edit: December 22, 2022, 02:50:28 pm by tggzzz »
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: Kalvin

Offline Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: A microcontroller programming language
« Reply #561 on: December 22, 2022, 02:52:29 pm »
Talking about the NULL pointers: Please introduce a proper keyword for denoting a NULL pointer value, for example null or nullptr.

Or avoid "the billion dollar mistake" altogether.
https://en.wikipedia.org/wiki/Null_pointer#History

I agree 100%.

Edit: Probably Ada or some other safety-driven language might provide a guidance how to implement this well in the language grammar.
« Last Edit: December 22, 2022, 02:56:31 pm by Kalvin »
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19723
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: A microcontroller programming language
« Reply #562 on: December 22, 2022, 03:03:37 pm »
Why not provide a construct that directly helps people doing low-level embedded programming?

For example, a select statement that is similar to a C switch statement:
Code: [Select]
select {
    case event1
        // handle the event
        ...
        break ;
    case event2
        // handle the event
        ...
        break ;
}
That statement would pause until either of the events occur and then execute the code within the relevant case. Although the select waits on several events, only one of the events would be handled by the statement when an event occurs.

An event could be any of:
  • input available
  • output completed
  • a timeout
  • a message from another thread

As anyone who has done embedded programming will recognise, with those constructs a vast range of embedded algorithms can be simply, easily, and understandably implemented.
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 Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #563 on: December 22, 2022, 04:44:36 pm »
Why not provide a construct that directly helps people doing low-level embedded programming?

For example, a select statement that is similar to a C switch statement:
Code: [Select]
select {
    case event1
        // handle the event
        ...
        break ;
    case event2
        // handle the event
        ...
        break ;
}
That statement would pause until either of the events occur and then execute the code within the relevant case. Although the select waits on several events, only one of the events would be handled by the statement when an event occurs.

An event could be any of:
  • input available
  • output completed
  • a timeout
  • a message from another thread

As anyone who has done embedded programming will recognise, with those constructs a vast range of embedded algorithms can be simply, easily, and understandably implemented.

Once you start to talk about events, time, resume, suspend etc then we're no longer talking language but OS.
“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 #564 on: December 22, 2022, 04:58:44 pm »
Talking about the NULL pointers: Please introduce a proper keyword for denoting a NULL pointer value, for example null or nullptr.

Or avoid "the billion dollar mistake" altogether. https://en.wikipedia.org/wiki/Null_pointer#History

That would be far more useful than diddling with syntax.

Yes I spent a little bit of time looking at that. PL/I was an early language that supported pointers and they are opaque. You cannot do pointer arithmetic in PL/I (or Ada) nor would I want to support that either. This is the core of many of C's problems the ease with which the programmer can create addresses.

I think 99% of the problems would vanish when pointer arithmetic is removed. So I must ask, what do people need this for when using C? Why is it so relevant? What downsides would ensue if this were not possible? what would need to be included in a language to compensate for loss of pointer arithmetic and the ability to set pointers to hard numeric values?
“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 brucehoult

  • Super Contributor
  • ***
  • Posts: 4069
  • Country: nz
Re: A microcontroller programming language
« Reply #565 on: December 22, 2022, 05:18:46 pm »
Yes, all args are passed by ref. To achieve pass by value (that is, pass a ref to a temp copy) one just surrounds the arg in parens:

omfg. I am without words.

You just threw away a huge chunk of performance, as well as compatibility with all existing libraries and OS interfaces.
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19723
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: A microcontroller programming language
« Reply #566 on: December 22, 2022, 05:59:33 pm »
Why not provide a construct that directly helps people doing low-level embedded programming?

For example, a select statement that is similar to a C switch statement:
Code: [Select]
select {
    case event1
        // handle the event
        ...
        break ;
    case event2
        // handle the event
        ...
        break ;
}
That statement would pause until either of the events occur and then execute the code within the relevant case. Although the select waits on several events, only one of the events would be handled by the statement when an event occurs.

An event could be any of:
  • input available
  • output completed
  • a timeout
  • a message from another thread

As anyone who has done embedded programming will recognise, with those constructs a vast range of embedded algorithms can be simply, easily, and understandably implemented.

Once you start to talk about events, time, resume, suspend etc then we're no longer talking language but OS.

Sorry, that's simply not true for multiple languages, Ada and SPARK amongst others.

Some processors have that functionality implemented in hardware. No RTOS necessary. And very good they are too for real-time embedded applications.

I you started this thread because you are interested in language features that would help embedded applications. Has that changed?

I've been pondering the idea of attempting to create a new (compiled) programming language specifically designed for hardware programming, microcontrollers
....
So I could start by asking what people's views are here, what do you - as an MCU developer - find good...
« Last Edit: December 22, 2022, 06:01:38 pm by tggzzz »
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: 8203
  • Country: fi
Re: A microcontroller programming language
« Reply #567 on: December 22, 2022, 06:04:30 pm »
Ada has a major blooper too as they are using parenthesis () for array index instead of brackets []. Now it is impossible to determine whether a(n) is a function call or an array element access, without checking the actual definition.

Yeah, I hate this kind of implicit "you have to know what X is, or have an IDE tell you" thing. I don't do C++ a lot, but when I do, not once I have mistaken function argument that is passed as reference vs. passed by value. There is difference (added &) in function definition, but at call site it looks exactly the same! Yet I think this is such large fundamental difference (whether my local variable might get modified or not) that I, as a caller, want to make that distinction, so I like the C pointer way of having to do that. (Minus points for C for the "arrays decay as pointers automagically" feature, kinda ruins it.)
 
The following users thanked this post: newbrain, DiTBho

Offline Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #568 on: December 22, 2022, 06:38:43 pm »
Yes, all args are passed by ref. To achieve pass by value (that is, pass a ref to a temp copy) one just surrounds the arg in parens:

omfg. I am without words.

You just threw away a huge chunk of performance, as well as compatibility with all existing libraries and OS interfaces.

Ha! but not without expletives!

OK since you do want to discuss this with me, let me respond.

I'm referring to the general policy for arg passing, ultimately an implementation could do this in various ways (pass in a register for example). I'm not really referring to the implementation but to the semantics, I don't think I made that clear.

So "pass by reference" here is meant to indicate that the callee can change something in the datum that's been passed. That's the default convention, and if the the caller want's to prevent a callee from changing the value of an arg, they'd simply make that arg an expression with ( and ).

This leads to increased performance because unless the developer wants to pass by value, they can write the code and just let args pass by ref, meaning passing a bunch of structures, strings, arrays or combinations of these will entail nothing more than pushing a pointer onto the stack!

Look at how often C code passes args by address too, I mean most code wants to pass by address so why not make that the default mode and reserve the extra syntax for the less common cases where we want to pass by value? Instead we have calling code littered with & and called code littered with *.

As for compatibility with other languages I've said nothing about interop, naturally when calling code written in a different language then that code's convention must be honored.


« Last Edit: December 22, 2022, 08:43:03 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 Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #569 on: December 22, 2022, 06:57:58 pm »
Ada has a major blooper too as they are using parenthesis () for array index instead of brackets []. Now it is impossible to determine whether a(n) is a function call or an array element access, without checking the actual definition.

Yeah, I hate this kind of implicit "you have to know what X is, or have an IDE tell you" thing. I don't do C++ a lot, but when I do, not once I have mistaken function argument that is passed as reference vs. passed by value. There is difference (added &) in function definition, but at call site it looks exactly the same! Yet I think this is such large fundamental difference (whether my local variable might get modified or not) that I, as a caller, want to make that distinction, so I like the C pointer way of having to do that. (Minus points for C for the "arrays decay as pointers automagically" feature, kinda ruins it.)

This is far from clear cut. After all an array and a function are in an abstract sense the same, they are (mathematically) mappings from an input space to an output space. One might also remove an array and implement it as a function (or vice verse)  in some code update, all the code would remain unchanged, no need to replace [ and ] with ( and ) all over the place.

Why does one need to care about how such a mapping is implemented when looking at code? we're putting something in and getting something out, how that's done should (IMHO) have no bearing on the calling code's comprehension.

Functional programming actually leverages a concept of "memoization", where a call to a function with a set of args, has the result cached so that a later call with the same args, returns the same result minus the computational overhead of having to evaluate it again, an array is a great way to implement memoization in many cases.

So I'm just not convinced myself, its an easy thing to do, altering the grammar for that is almost trivial, but you then run the risk of losing symbolic characters that might have some better use in the future, there really aren't that many standard (ASCII) symbols available.

« Last Edit: December 22, 2022, 07:05:12 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 Kalvin

  • Super Contributor
  • ***
  • Posts: 2145
  • Country: fi
  • Embedded SW/HW.
Re: A microcontroller programming language
« Reply #570 on: December 22, 2022, 07:28:21 pm »
Ada has a major blooper too as they are using parenthesis () for array index instead of brackets []. Now it is impossible to determine whether a(n) is a function call or an array element access, without checking the actual definition.

Yeah, I hate this kind of implicit "you have to know what X is, or have an IDE tell you" thing. I don't do C++ a lot, but when I do, not once I have mistaken function argument that is passed as reference vs. passed by value. There is difference (added &) in function definition, but at call site it looks exactly the same! Yet I think this is such large fundamental difference (whether my local variable might get modified or not) that I, as a caller, want to make that distinction, so I like the C pointer way of having to do that. (Minus points for C for the "arrays decay as pointers automagically" feature, kinda ruins it.)

This is far from clear cut. After all an array and a function are in an abstract sense the same, they are (mathematically) mappings from an input space to an output space. One might also remove an array and implement it as a function (or vice verse)  in some code update, all the code would remain unchanged, no need to replace [ and ] with ( and ) all over the place.

Why does one need to care about how such a mapping is implemented when looking at code? we're putting something in and getting something out, how that's done should (IMHO) have no bearing on the code comprehension.

So I'm just not convinced myself, its an easy thing to do, altering the grammar for that is almost trivial, but you then run the risk of losing symbolic characters that might have some better use in the future, there really aren't that many standard (ASCII) symbols available.

If you define brackets [] as an operator, that would keep some possibilities open for future language extensions. For example in C++ it is possible to define operator [] for a new class.

You can argue that a function call and array indexing are both mappings, but in practice (ie. the code generated by the compiler) accessing an array element is fundamentally different from a function call. In summary: using different symbols for indexing and function arguments makes good sense, and there is no reason to repeat the Ada blunder again.

This might be interesting reading: Ada 83 to Ada 2012: lessons learned over 30 years of language design
https://www.researchgate.net/profile/S-Taft/publication/286243707_Ada_83_to_Ada_2012/links/56e02f1408aec4b3333d0201/Ada-83-to-Ada-2012.pdf Unfortunately I do not have access to the text of the actual presentation.

This may be a little controversial: It is now year 2022, and modern OSs have support for Unicode character set. Basically there is no reason to use plain ASCII character set, so the language could use some symbols defined in Unicode character set. To be clear here, I do not want to see a new APL either. :)
« Last Edit: December 22, 2022, 07:49:39 pm by Kalvin »
 

Offline tggzzz

  • Super Contributor
  • ***
  • Posts: 19723
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: A microcontroller programming language
« Reply #571 on: December 22, 2022, 07:46:34 pm »
Why not provide a construct that directly helps people doing low-level embedded programming?

For example, a select statement that is similar to a C switch statement:
Code: [Select]
select {
    case event1
        // handle the event
        ...
        break ;
    case event2
        // handle the event
        ...
        break ;
}
That statement would pause until either of the events occur and then execute the code within the relevant case. Although the select waits on several events, only one of the events would be handled by the statement when an event occurs.

An event could be any of:
  • input available
  • output completed
  • a timeout
  • a message from another thread

As anyone who has done embedded programming will recognise, with those constructs a vast range of embedded algorithms can be simply, easily, and understandably implemented.

Once you start to talk about events, time, resume, suspend etc then we're no longer talking language but OS.

Sorry, that's simply not true for multiple languages, Ada and SPARK amongst others.

Some processors have that functionality implemented in hardware. No RTOS necessary. And very good they are too for real-time embedded applications.

I you started this thread because you are interested in language features that would help embedded applications. Has that changed?

No nothing has changed, and there might be some merit in what you're suggesting, I might be wrong. My position is though that to start designing such capabilities into the language begins to impose a particular design pattern for events, threads, scheduling and so on and that might be very restrictive to the broader community of users.

But you are already doing exactly that with the features you are proposing including/excluding from your language. Other languages also, necessarily, do that in their own ways too (Examples: statistics processing languages, modelling languages, HDLs, business-oriented languages, even spreadsheets :) )

Quote
Better I feel for the designer to be free to select such an important aspect of a platform and just rely on the language to help them interact with that platform, but I might be wrong, I'd need to look into this much more and I guess that's a large scope creep at this point (but rest assured we could add keywords for some of the stuff without any problems).

It is indeed scope creep. But then every departure from keywords and syntax into useful behaviour is also scope creep.
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 Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #572 on: December 22, 2022, 08:31:38 pm »
Why not provide a construct that directly helps people doing low-level embedded programming?

For example, a select statement that is similar to a C switch statement:
Code: [Select]
select {
    case event1
        // handle the event
        ...
        break ;
    case event2
        // handle the event
        ...
        break ;
}
That statement would pause until either of the events occur and then execute the code within the relevant case. Although the select waits on several events, only one of the events would be handled by the statement when an event occurs.

An event could be any of:
  • input available
  • output completed
  • a timeout
  • a message from another thread

As anyone who has done embedded programming will recognise, with those constructs a vast range of embedded algorithms can be simply, easily, and understandably implemented.

Once you start to talk about events, time, resume, suspend etc then we're no longer talking language but OS.

Sorry, that's simply not true for multiple languages, Ada and SPARK amongst others.

Some processors have that functionality implemented in hardware. No RTOS necessary. And very good they are too for real-time embedded applications.

I you started this thread because you are interested in language features that would help embedded applications. Has that changed?

No nothing has changed, and there might be some merit in what you're suggesting, I might be wrong. My position is though that to start designing such capabilities into the language begins to impose a particular design pattern for events, threads, scheduling and so on and that might be very restrictive to the broader community of users.

But you are already doing exactly that with the features you are proposing including/excluding from your language. Other languages also, necessarily, do that in their own ways too (Examples: statistics processing languages, modelling languages, HDLs, business-oriented languages, even spreadsheets :) )

Quote
Better I feel for the designer to be free to select such an important aspect of a platform and just rely on the language to help them interact with that platform, but I might be wrong, I'd need to look into this much more and I guess that's a large scope creep at this point (but rest assured we could add keywords for some of the stuff without any problems).

It is indeed scope creep. But then every departure from keywords and syntax into useful behaviour is also scope creep.

Thanks.

Languages describe behavior, so before you can describe behavior, represent it, you need language and languages have - need - grammar - so I don't quite understand dismissive remarks about the significance of grammar. Being dismissive, glib about this aspect of programming languages is why we have so many problems with C++ and various other languages. If the grammar is crippled you pay a long term price and that can be a high price as the many examples I've shared show.

I mean it seems like I'm hearing this sometimes "I want to talk about programming languages but do not care about the superficial grammar, syntax BS" - to which I can only reply "Very well, in that case use assembler".

« Last Edit: December 22, 2022, 09:28:17 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 Sherlock HolmesTopic starter

  • Frequent Contributor
  • **
  • !
  • Posts: 570
  • Country: us
Re: A microcontroller programming language
« Reply #573 on: December 22, 2022, 08:39:22 pm »
Ada has a major blooper too as they are using parenthesis () for array index instead of brackets []. Now it is impossible to determine whether a(n) is a function call or an array element access, without checking the actual definition.

Yeah, I hate this kind of implicit "you have to know what X is, or have an IDE tell you" thing. I don't do C++ a lot, but when I do, not once I have mistaken function argument that is passed as reference vs. passed by value. There is difference (added &) in function definition, but at call site it looks exactly the same! Yet I think this is such large fundamental difference (whether my local variable might get modified or not) that I, as a caller, want to make that distinction, so I like the C pointer way of having to do that. (Minus points for C for the "arrays decay as pointers automagically" feature, kinda ruins it.)

This is far from clear cut. After all an array and a function are in an abstract sense the same, they are (mathematically) mappings from an input space to an output space. One might also remove an array and implement it as a function (or vice verse)  in some code update, all the code would remain unchanged, no need to replace [ and ] with ( and ) all over the place.

Why does one need to care about how such a mapping is implemented when looking at code? we're putting something in and getting something out, how that's done should (IMHO) have no bearing on the code comprehension.

So I'm just not convinced myself, its an easy thing to do, altering the grammar for that is almost trivial, but you then run the risk of losing symbolic characters that might have some better use in the future, there really aren't that many standard (ASCII) symbols available.

If you define brackets [] as an operator, that would keep some possibilities open for future language extensions. For example in C++ it is possible to define operator [] for a new class.

You can argue that a function call and array indexing are both mappings, but in practice (ie. the code generated by the compiler) accessing an array element is fundamentally different from a function call. In summary: using different symbols for indexing and function arguments makes good sense, and there is no reason to repeat the Ada blunder again.

This might be interesting reading: Ada 83 to Ada 2012: lessons learned over 30 years of language design
https://www.researchgate.net/profile/S-Taft/publication/286243707_Ada_83_to_Ada_2012/links/56e02f1408aec4b3333d0201/Ada-83-to-Ada-2012.pdf Unfortunately I do not have access to the text of the actual presentation.

This may be a little controversial: It is now year 2022, and modern OSs have support for Unicode character set. Basically there is no reason to use plain ASCII character set, so the language could use some symbols defined in Unicode character set. To be clear here, I do not want to see a new APL either. :)

Ada now uses [ and ] but as syntax for array initialization:

https://learn.adacore.com/courses/whats-new-in-ada-2022/chapters/array_aggregates.html

Hmm Ada also lets you specify the type of the subscript expression, interesting...
“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 brucehoult

  • Super Contributor
  • ***
  • Posts: 4069
  • Country: nz
Re: A microcontroller programming language
« Reply #574 on: December 23, 2022, 02:27:46 am »
Yes, all args are passed by ref. To achieve pass by value (that is, pass a ref to a temp copy) one just surrounds the arg in parens:

omfg. I am without words.

You just threw away a huge chunk of performance, as well as compatibility with all existing libraries and OS interfaces.

Ha! but not without expletives!

OK since you do want to discuss this with me, let me respond.

I'm referring to the general policy for arg passing, ultimately an implementation could do this in various ways (pass in a register for example). I'm not really referring to the implementation but to the semantics, I don't think I made that clear.

So "pass by reference" here is meant to indicate that the callee can change something in the datum that's been passed. That's the default convention, and if the the caller want's to prevent a callee from changing the value of an arg, they'd simply make that arg an expression with ( and ).

This leads to increased performance because unless the developer wants to pass by value, they can write the code and just let args pass by ref, meaning passing a bunch of structures, strings, arrays or combinations of these will entail nothing more than pushing a pointer onto the stack!

Ugh.

Code: [Select]
procedure foo(i : integer)
  var i : integer = 1;
  procedure bar(j : integer)
    i := i + 1;
    j := j + 1
  end
  bar(i);
  print(i)
end

What is printed?
 
The following users thanked this post: newbrain, MK14, DiTBho


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf