Many high level languages actually let you find the current and maximum lengths of strings or the rank and bound of arrays at runtime. C does not, sure you can write code to somehow create abstractions that do that if you really want, but that's really what languages are for, to reduce the need for such drudgery.
at what cost? as a language designer, you should already have the answer in your belt.
Well you need to define "cost" first and you haven't. Does it mean man hours to implement in the compiler? memory used for the metadata? performance costs in simply having the metadata, performance cost in accessing the metadata or what? It's a totally valid question and one that will certainly have an answer once we define "cost".
btw, you can start designing one "highly managed" language if you want to, you can start a list of mostly used features and we would love to try... if what you have in mind is that (highly managed language), looking at C is a bad start. start looking at other highly managed language such as maybe Python? or Rust? or whatever, i dont know, i'm not a proficient "all languages" programmer... C is not a managed language. but most people use it. its like automatic car vs manual car. both will have market. i choose manual car... lets see if one day manual car extinct.
I'm certainly not advocating a "managed" language in the sense of C# or Java, I'm looking a compiled imperative language with a grammar borrowed mostly from PL/I but including parts of other grammars too.
At a minimum the language would include:
1. More storage classes than C (defined, based etc)
2. More data types including decimal/BCD and strings of fixed or variable length.
3. Arbitrary rank arrays with optional bound specifiers.
4. Distinguish between function and procedures.
5. Fine control over padding and alignment and field ordering etc.
6. No object oriented features, no GC, no virtual functions and so on.
7. No need for "forward declarations"
8. Nested functions/procedures.
9. Some kind of "computed" goto support.
10. No reserved words.
11. No explicit pointer arithmetic, like ptr++ and ptr-- and so on.
12. Invocable variables (a simpler form of C's function pointer)
That's the basic initial list anyway, entirely reasonable and feasible and something I've implemented successfully in the past.
What I'd like to add is stuff that might be specific to MCU development, features that are not so relevant for conventional programming, (like for example constant execution time functions/procedures where the execution is - or strives to be - independent of state or arguments).
I don't the there's an appreciation of the benefits of a no-reserved-words grammar. We can add new keywords freely and never break backward compatibility.
Look at this draft example:
func get_fastest_motors_speed (X) float(binary(128)) optimize(speed) determinate
{
arg X binary(16);
return (something);
}
Those keywords decorating the function definition, could grow, we could add new keywords and never break existing code (the various attributes too can specified in any order).
That's just for example, the specific terms used are made up, not really to be taken as definitive, just made up to show the potential flexibility.