Design a better "C" - Page 1
Forum section: electronics / general

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 21, 2021, 08:34:41 pm
content: Yeah I know this is a very recurring topic. But since we have talked a lot about C here, its strong points, and (very often) its shortcomings, I'm curious what you guys would propose for a "better C" language. Especially from the POV of people that are mostly EEs (and only a few of them are pure software guys, I think).Syntax could be different. The key here would be to keep the essence of C: simplicity, portability, high-level and low-level enough, and the potential for wide acceptance. Meaning probably avoiding "uncomfortable" constructs or too exotic approaches, and, of course, making it usable on small embedded targets.You can mention existing candidates (Rust comes to mind, but there are also attempts such as Zig and Odin, and lots of others...), but what would be interesting, instead of just mentioning them, would be to detail what you think is great in them for a C replacement, and what you think isn't that great. I'm sure many of you have considered alternatives over the years, and yet are still using C. So, getting to the bottom line of what would make this possible could be enlightening. Hopefully.The final conclusion may very well be that there won't be a real replacement for C in areas it's used most these days. But some ideas could be interesting. Let's try not to turn this into a language war, it's just meant to be constructive.

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: July 21, 2021, 09:42:28 pm
content: As an EE, the main reason for choosing a particular language is having a compiler available for the microcontroller that you are using. Most manufacturers just provide a compiler that supports C and therefore Most of the projects in which I have worked are written in C, but if they just supported another language (C++, Ada, etc) I would use it. The language is not that important, as programs that run in microcontrollers are normally not that big and therefore it is easier to maintain them (although some projects even require running an embedded Linux distro in the MCU. One of my professors said to us that we shouldn’t try to invent a new way to write an if but something new to use it for, and I have followed that recommendation since then.However, there are some things that make some languages nicer. Standardization improves portability and being able to write inline assembly routines is a must if you’re working with DSPs or control systems that operate in real time. Therefore, it would be nice if interruptions where included in the C standard, as each manufacturer uses a different way to specify which functions should be mapped to them. Being able to specify the location in which variable should be used (for mapping registers) without using linker scripts would also be useful, as Ada allows.On the other hand, nowadays FPGAs allow implementing application specific processors quite easily, so being able to easily write a compiler backend for them might become same thing important in the near future when choosing a programming languageFinally, I wouldn’t use a language which is not ISO standardized, nor an interpreted one. The first ones tend to change too fast breaking the compatibility of old programs with new compilers and the second ones are too slow for these applications. JIT compilation should also be avoided in real time applications as well as garbage collectors as they impede predicting the amount of time that a function will require for being executed. Additionally, in some industries, just ISO standardized languages are allowed, which is something that also needs to be taken into account when choosing it

author: PlainName
author_rank: Super Contributor
timestamp: July 21, 2021, 10:26:10 pm
content: I wouldn't mind some basic C++ stuff. Just objects with inheritance. Perhaps overloading. Forget template stuff and pretty much everything else. Streams... well, if you must I suppose.

author: David Hess
author_rank: Super Contributor
timestamp: July 21, 2021, 11:12:44 pm
content: I would fix the problem of operations returning the wrong result size; real multipliers return a product which is twice the size of the operands. I would add fixed point radix tracking; bookkeeping is exactly what computers are good at. Some old "improved" C compilers for DSP and embedded use did both of these.

author: AntiProtonBoy
author_rank: Frequent Contributor
timestamp: July 22, 2021, 12:06:29 am
content: Quote from: dunkemhigh on July 21, 2021, 10:26:10 pmInheritance is overrated. Great for some niche stuff, but you are better off with the composition pattern. As for templates, they are awesome, especially when used together with concepts. But the best part of C++ is RAII.

author: james_s
author_rank: Super Contributor
timestamp: July 22, 2021, 12:11:13 am
content: I quite like C as it is actually, but if there's one thing that comes to mind that I'd change, it would be to give it the ability to pass arrays to and from functions. Having learned Python first that is something that caused me some grief coding in C.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 22, 2021, 05:53:37 am
content: Removing "implementation defined" or "undefined behavior" aspects whenever possible.Replacing them with explicit directives etc.For example, remove strict aliasing rule, extend therestrictkeyword if necessary to allow the same optimizations, and more. (It might be enough already as it is, to enable optimizations, people just need to start using it. I don't know.)Adding many of the compiler flags / extensions to the language itself.For example, instead of having to pack a struct to obtain the same result across different platforms, add official language directives that allow the same alignment results.I won't suggest any large or fundamental changes because quite frankly, everybody has their own ideas about them, all of them have been tried multiple times, and for "some reason", C is still there but most of the "improved" languages have all but vanished.Maybe some syntactical differences like being able to return multiple values from a function without specifying a single-use struct type for that, but these are not so important. Too many such changes easily alienate existing C developers because having to know many new rules is a mental burden. Think about C++ with so many rules it takes 20 years to learn it properly, then rest of your life to keep on track on all the new features on each new standard, and thus everyone using a different subset. Not a good situation IMO, we don't want this.

author: cfbsoftware
author_rank: Regular Contributor
timestamp: July 22, 2021, 06:24:26 am
content: Quote from: SiliconWizard on July 21, 2021, 08:34:41 pmNOTE: I have to declare that I have a commercial interest in this topic as I am the creator of Astrobe - An IDE for ARM Cortex-M Microcontrollers and Xilinx FPGA Systems so it is difficult not to be biased.Oberon-07 is my language of choice for programming microcontrollers. A summary of the features that make it suitable for this work is here:https://www.astrobe.com/Oberon.htmElektor Magazine ran an article a few years ago:https://www.elektormagazine.com/labs/easy-sceptre-programming-with-oberon-07I have attempted to get some objective measure of the comparative reliability of C and Oberon-07 when used for embedded software development. In order to do this I referred to the MISRA C guidelines:>From Wikipedia: "MISRA C is a set of software development guidelines for the C programming language developed by MISRA (Motor Industry Software Reliability Association). Its aims are to facilitate code safety, security, portability and reliability in the context of embedded systems"I took the 142 rules of the MISRA-C:2004 "Guidelines for the use of the C language in critical systems" and applied them to Oberon-07. I discovered that more than 70% of the rules are NOT required when programming in Oberon-07. They are either already enforced by the language or are not applicable.

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: July 22, 2021, 07:09:00 am
content: Quote from: Siwastaja on July 22, 2021, 05:53:37 amImplementation defined int size is really a problem. Even though uint_fast8_t and similar types solve that partially, it would be nice to be able to specify the minimum amount of bits that each variable should have (as far as I know, float numbers do not have that possibility). That would reduce a lot of headaches when porting a program to a different microcontroller

author: Siwastaja
author_rank: Super Contributor
timestamp: July 22, 2021, 07:32:11 am
content: Quote from: Just_another_Dave on July 22, 2021, 07:09:00 amOptional ranges, like in VHDL.int range -1234,2345 ivar;float range -12.3,+999.3 fvar;enabling the compiler to do static error checking, optimization with assumptions about the numerical range, and obviously, choose optimum storage size for implementation defined size storage (like the current _fast_t).Also makes the programmer document their assumptions way better than having to use free form comments to do that.Inside structs, bitfields exist already, all that is needed to remove arbitrary ordering and padding which is currently implementation defined, and standardize one way of doing it.Current standard is utterly stupid because itallowsarbitrary padding of structs for performance reasons, but doesnotallow reordering. Have an explicit directive tell that exact binary representation either is necessary, or isn't. In latter case, allow reordering, optimizing away, or automatic "unionization" of members; compilers are pretty capable of static analysis today. Even just the automatic reordering would allow the classical "in decreasing size" ordering (with some simplistic cache line analysis) while maintaining the readability of the code.Basically, at general level, directives for the programmer to describe whether certain memory layout is desired, or if the compiler can do whatever it wants to obtain the functional result. The current standard is inconsistent here, making C a mixed high level functional / low level near-hardware language with a few traps.

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 10:38:57 am
content: Quote from: Just_another_Dave on July 21, 2021, 09:42:28 pmPresumably you also only use processors and memory systems which don't have any statistical optimisation techniques. They significantly improve performanceon average, at the expense of making it impossible topredictworst-case behaviour. The prime example is caches, but also include interrupts.

author: PlainName
author_rank: Super Contributor
timestamp: July 22, 2021, 10:47:28 am
content: QuoteThat kind of flag tends to be hardware-dependent though, doesn't it? Or, at least, at a compiler (as opposed to language) level. Although it would be pretty unlikely to find that specific thing unsupported, the potential is there (just as a byte may not be 8 bits).

author: Ed.Kloonk
author_rank: Super Contributor
timestamp: July 22, 2021, 10:54:45 am
content: Quote from: james_s on July 22, 2021, 12:11:13 amI thought that Python was intended to suppliment C for the reasons that the OP mentioned.

author: DiTBho
author_rank: Super Contributor
timestamp: July 22, 2021, 10:58:17 am
content: Quote from: dunkemhigh on July 22, 2021, 10:47:28 amYes, and it's a mess ... too many flags for ARM, many many more for MIPS, and they are all different.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 22, 2021, 10:59:38 am
content: Quote from: dunkemhigh on July 22, 2021, 10:47:28 amNo, I mean like a keyword to enable a padding rule of self-aligning all variables and aligning the whole struct by 8. Such setting would work in 99.999% actually existing platforms and also be very efficient.Because even now, if you use stdint.h for every variable and forget the packed attribute, chances are high it still works through most architectures because the padding rules are mostly the same regardless of the word with: just add padding bytes after each variable so that the next oneself-aligns. Some architectures may allow more loose alignment than self-alignment, for example afloatstarting at any addr%4, or a 8-bit architecture can allow any variable to be unaligned because accessing them is the same amount of work anyway. But self-alignment is practicallynever wrong, and if you could force the compiler to dothat, then you wouldn't have the stupid choice between potential binary protocol incompatibility (no attributes), or potential performance issues (packed attribute). Now we are forced to usepackedand manually add padding in such cases. Maybe this isn't bad because explicit over implicit, though...I haven't thought this over enough to say if it's practical or a good idea. Just popped in my mind.

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: July 22, 2021, 11:40:13 am
content: Quote from: tggzzz on July 22, 2021, 10:38:57 amIn general, processors used in control loops that need to operate in real time don’t have most of those things. Interrupts are the only exception, so they need to be used carefully to avoid blocking the main loop. However, as they are frequently used to react to critical events, in most projects in which I have worked it’s not so important to predict the amount of time required to execute the main loop, but to ensure that the amount of cycles required to execute each interrupt falls within an specified range.Additionally, most interrupts are usually periodic (for example a timer) and the others frequently came from protection systems, so they are more important that anything else.More complex systems don’t normally have such demanding requirements in terms of reaction time, allowing to respond to the received stimulus in hundreds of milliseconds or even more. Python would still be too slow for them (it won’t be able to execute the program fast enough to meet the specifications even if you could predict how much time would be required), but a real time os can be used even though it can add certain degree of uncertainty.Regarding JIT, variable delays can be a nightmare for control loops stability. Therefore, it is better to do things slower but with a constant speed than to apply optimizations iteratively

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 12:05:36 pm
content: Quote from: Just_another_Dave on July 22, 2021, 11:40:13 amFor loop control stability, any form of timing variability is a nightmare!I've seen too many people not understand the effects of caches.I've seen too many people think isolated unit tests created via TDD are sufficient. "You can't inspect/test quality into product; it has to be designed."

author: Siwastaja
author_rank: Super Contributor
timestamp: July 22, 2021, 12:38:50 pm
content: tggzzz's similar points have been addressed before, but I repeat that the key to success with non-deterministic timing is to keep thing simple enough that it's easy to prove theworstcase being good enough, and add some margin on the top of that. With today's performant parts, addinga lotof margin is usually trivial.Increasing the amount of margin reduces uncertainties due to small mistakes we human beings make. While you could model the crystal structure of steel and control the melting process perfectly, obtaining parts with exact material thickness enough to last, in reality ample safety margins are added. Same goes with programming.Practical example: You need a peak current limit. Available voltage is 100V and lowest possible inductance under maximum possible current and worst case temperature is 100µH. Now current rises at 100V/100µH = 1A/µs. Taking comparator offset voltages into account, the current sense comparator is guaranteed to generate output when exceeding 10A. Inductor saturation current (at which the 100µH inductance was calculated) is 15A. There is hence 5µs of time to react. Say comparator delay is 1µs, and the MOSFET gate driver delay is 100ns. Software has to be able to trig the interrupt, enter it, change the IO state in 3.9µs.Deciding you only disable interrupts for critical sections of max. 10 clock cycles, Cortex-M interrupt latency being 12 cycles, and the relevant IO operation placed right at the beginning of the ISR, taking say 3 clock cycles, plus let's say another 2 for crossing the clock boundary from the CPU core to GPIO domain, the delay is 27 clock cycles. Say at Fcpu=100MHz, this is 0.27µs, way less than 3.9µs. 3.9µs would be 390 clock cycles, and ****cking the code up so badly requires fatal flaws in the designer's skill of building software-controller power supplies. Now a Cortex-M4 or -M7 might optimize the interrupt entry because a lower priority interrupt has already started stacking, so sometimes it'sfasterthan this, making it non-deterministic and jittery. But in this case, having it "too fast" is impossible.Using CPUs with configurable interrupt priorities ease the task. It's very rare the possible tree of nested interrupts is so complex you have hard time analysing it. Usually you don't have gazillion important things thatallrequire actions withina fewclock cycles, if you do, consider a CPLD / an FPGA.Caches - don't need them in timing critical control applications. Turn off, if not already disabled at startup. These top-of-the-line MCUs which are fancy enough to come with caches, also tend to come with core-coupled memories so you can run the timing critical code off there, with perfectly deterministic - and FAST! - memory access timing. Even if you enable caches (for example, to speed up the average performance of your bloated UI), critical interrupt code placed in ITCM does not have any penalty from this.

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 01:10:57 pm
content: Quote from: Siwastaja on July 22, 2021, 12:38:50 pmThat's easy and sufficientiffyou canprovethe worst case time. How do you prove the worst case time (a) without caches (b) with caches?To me "measurement" isn't "proof", although it can be "validation". You can't test quality into a product!QuoteTurning off instructionanddata caches is a valid approach - but it implies a large area of silicon is unused, and that a cheaper and lower power alternative is probably available.Interrupts bring their own problems (see the Mars Pathfinder!), which can be very difficult to analyse and get right as features are added.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 22, 2021, 04:28:13 pm
content: Quote from: tggzzz on July 22, 2021, 01:10:57 pmCortex-M interrupt latency is reliably specified, guaranteed by ARM.Vector table can be relocated in ITCM or RAM, ISR itself can be in ITCM. Resulting access patterns are simple.Output assembly listing, count clock cycles of instructions that lead to the important operation. Instruction set manual gives the range of clock cycles a particular instruction takes.Additionally, go through all critical sections that run interrupts disabled; count the clock cycles. This is the worst-case delaybeforethe interrupt latency.If a higher-priority interrupt can pre-empt a less urgent but still timing-critical interrupt, add the maximum duration of the higher-priority interrupt. This highly motivates to keep the highest priority ISRs short because counting cycles from an assembly listing of a complex state horror with a lot of branches will be a nightmare. If the hi-prio ISR needs to be complex, you can split it in two, by demoting the interrupt priority by generating a software interrupt request with lower priority from the hi-prio ISR. This way, you can do the absolutely timing critical thing first, then continue more complex code at lower priority so it can be pre-empted by "medium-importance" stuff.Run all such code from ITCM. Running from flash is OK too, just slower and jittery, you can still guarantee worst-case longest timing by assuming the number of configured wait states happen forevery read; real-world average performance will be just better.Yes, this is some manual work, but usually you don't need to go this far too often because in real world projects, not every signal, not every logical operation is so sensitive to timing.All of this manual work has a risk of human error. Measurement can be used as a verification step, as you note. Margins are important in any case, against small errors. If you write low level C, how to do it right, don't use random bloated libraries, and finally, check the assembly listing, there just is no way expected 20 cycles becomes 200 cycles.Everything in real world has range for errors. You don't pilot an airliner at millimeter accuracy.QuoteAssume cache miss for every read. Actual average (and possibly even worst-case, but you can't trust this) is way way better but hey, you get your worst-case guarantee.This being said, I don't understand why you are bringing up the caches so eagerly. Cycle-accurate, timing critical microcontroller code just isn't ran from a slow memory through cache, it makes no sense. Indeed, none of my projects on STM32F7 or H7 enable caches; they are wasted silicon. The fact these top-of-the-line micros include caches which are "wasted" silicon if not used is a moot point because such top tier micros have dozens and dozens of features being unused. For example, H7 has two CAN peripherals which take up quite some area because they have dedicated message RAMs roughly similar size to what a cache could be, yet you don't always need CAN. Same can be said about area used by Ethernet, USB, and so on. Custom ASIC for everything would be technically optimal solution but obviously impossible.

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 04:44:59 pm
content: Quote from: Siwastaja on July 22, 2021, 04:28:13 pmWhere the interrupt latency is guaranteed by design and specified in the datasheet, that is fine and practical. That's only a small part of real-time operation, of course. Of more interest is the maximum repetition frequency of the outer control loop in the entire system, and will have far more instructions.Cycle counting is theoretically possible, but I doubt it is practical unless the design toolset does the counting for you.Good luck trying to cycle count any operations inside an RTOS, e.g. thread swapping, mailboxes or semaphores with priority inheritance enabled.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 22, 2021, 04:54:52 pm
content: That is why I don't prefer to use RTOSes and don't understand people who market them as the best things since sliced bread for timing critical control. They bring poor concepts and abstractions (like threads) to describe parallelism, developed for non timing critical desktop/server apps, and known to be colossally difficult even there.This being said, when I get such market speech and ask for examples, they get so excited to tell me they did something which happensin a millisecond!!!I count time in nanoseconds thank you.Cycle counting the whole program is of course impractical, but often the really timing-critical part is only a dozen of instructions with no branches.Plain old interrupt hierarchy on bare metal is so much easier to analyse, IMHO. Just keep things simple.If large parts of control need to be totally jitter-free, i.e., minimum allowed == maximum allowed, then this is still possible but becomes so impractical and tedious on a general purpose MCU that indeed go to FPGA or your favorite XCORE.It's just my observation that such totally jitter-free controls are rare, almost always it's enough to guarantee some worst-case maximum time, and minimum time can be shorter.But this is again drifting off-topic but oh well that always happens anyway.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 22, 2021, 06:01:47 pm
content: Note: many of the points raised by Siwastaja - and others - are addressed in ADA.Actually, I would likely use ADA if:- It was more lightweight;- It could be used without a runtime (I know this point can be mitigated, you can design very minimal runtimes for ADA, but still...);- Related: writing your own runtime would be required if you want to do anything customized and/or use targets that do not have existing runtimes yet - doable but not completely trivial;- Code efficiency was a bit better...I don't mind the syntax. "Wirthian" languages are fine with me. But something a bit simplified wouldn't hurt.@cfbsoftware: I have considered Oberon actually. There's a lot to like about it. But I think Wirth went a bit too far with it. He removed so much that some things are even clunkier to express than with C. Also, all low-level stuff is supposed to be handled by the SYSTEM module - which is an approach that Wirth always cherished - but it does make writing portable low-level stuff very clunky.I have looked at other similar languages such as Component Pascal, Modula-3, etc. All are interesting in their own way, but, not quite there. At least for me. Worth a look though.One thing I often mention and that those languages have: support for modules. This is good. I f*cking want modules. (I think it's being discussed for C++?) You can have a look at D: its module implementation is nice.

author: bd139
author_rank: Super Contributor
timestamp: July 22, 2021, 06:32:26 pm
content: Ok I like this thread.Don't change C. Don't make a better C. C is the perfect C.A little story recently. Higher level and slightly more idealistic languages impose more constraints on the user which they are not aware of due to the preferred way of doing things. They might not be the right way based on what you're trying to achieve. Most software is fashion driven as well so most alternatives are people wandering in the forest looking for a sexy looking tree to spend the night rubbing up against...Recently I was asked to fix a participation tracking system for consolidating order commissions. This is a fairly simple problem in the scale of things but the dataset is quite large (3GB CSV). The first attempt was some junk in python with AWS lambda. That eventually cost a lot of money to run. The next attempt was written in python and ran on a proper server but it was slow so they added pooling and parallelism to utilise all the machine resources. This worked until they ran out of RAM. After profiling it I found it was spending about 60% of the wall clock time futzing organising the conceptual abstraction of the data structures which were lists and objects. I pictured the whole thing as a bunch of monkeys opening and closing filing draws and moving bits of paper around.It took 25 minutes to process it and it used 24Gb of RAM. Code was 12Kb.I sat down and thought about it from a machine perspective and came up with mmapping the source file, parsing the source file, processing it and then writing the output into a spare structure using malloc and overcommitting then jumping through the links in that and writing it out to final destination file. This inevitably ended up in C because it was closest to the API I was using (Linux libc)It took 18 seconds to process it and it used 4.2Gb of RAM. Code was 8Kb.The best thing is the entire problem took me about 4 hours to solve using tools that were already on my computer (gcc, vim, make, valgrind) and are fast, efficient and have a really really really low iteration time.For this I suffer some loss of safety and correctness but gain the ridiculous amount of power from throwing off the shackles of not being trusted near any of that RAM stuff...Epilogue: I'm waiting for them to work out how to run my C program in lambda next

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 08:16:11 pm
content: Quote from: Siwastaja on July 22, 2021, 04:54:52 pmNASA aren't afraid of a commercial RTOSs for controlling Martian rovers. Having one enabled them to "rescue" the Mars PathfinderQuoteThat is simply wrong.QuoteWhen you mention µs and ns (and jitter), you appear to be confusing "real time" and "fast".QuoteIn a real time system the results of a computation have to be produced before a deadline; if they miss the deadline then that is a failure. The problem isprovingthat they will be produced before the deadline, whether that deadline is 1ns, 1s or 86400s!Jitter is a separate issue, and should not be confused with speed.

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 08:19:25 pm
content: Quote from: bd139 on July 22, 2021, 06:32:26 pmI tend to agree. Throw away C's historic cruft, and make a better tool than C can ever be. (Yes, I am aware of what that doesn't say!).QuoteIf the results didn't have to be correct, I could have developed it in 1 hour and it would take 1s to run. Code size would be much smaller, too

author: madires
author_rank: Super Contributor
timestamp: July 22, 2021, 08:50:02 pm
content: Are today's software developers too lazy to learn and understand their programming languages? Is C insecure because software developers can't be bothered to take care about memory management? After moving to Rust will they start complaining about how cumbersome writing code is and ask for an AI doing their job?

author: Feynman
author_rank: Regular Contributor
timestamp: July 22, 2021, 09:02:37 pm
content: Well, C has its flaws for sure. But the beast is pretty much tamed with things like coding standards and static analysis tools. In my opinion the only real alternative is C++. It has the same performance and low level capabilities and offers some really helpful additions like the standard-library (std) and compile time features, for example.The only thing I can imagine is that even in embedded systems multi-core architectures could become the norm where functional languages have clear benefits. But on the other hand it's hard to believe that relatively simple single-core micro-controllers will go away any time soon.Long story short: C is here to stay.

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 09:50:40 pm
content: Quote from: madires on July 22, 2021, 08:50:02 pmWho cares whether or not someone defines them as "lazy".C is a language that very few people understand completely. Usually, if you ask a typical C programmer what, say, "volatile" guarantees, they will get it wrong one way or another. Most don't realise that until recently it was impossible to write a threading library in C! Then there are all the "simple" things that trip up many people. Can you, for example, "cast away constness", and why should that be impossible and possible?

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 09:55:43 pm
content: Quote from: Feynman on July 22, 2021, 09:02:37 pmFunctional languages aren't a panacea. Try doing I/O in a pure functional languageHowever, C and especially C++ deserve to be regarded as the new COBOL

author: cfbsoftware
author_rank: Regular Contributor
timestamp: July 22, 2021, 10:34:45 pm
content: Quote from: SiliconWizard on July 22, 2021, 06:01:47 pmCould you give me an example of where you think this applies please?QuoteNot ALL the low-level stuff needs to be handled by SYSTEM now. Only the stuff that can lead to obscure problems caused by memory corruption e.g. typecasts, accessing absolute memory addresses etc. Note also that SYSTEM is actually a 'pseudo module'. What looks like a procedure call is, more often than not, inline code. SYSTEM is just there to highlight to the code reader / maintainer that they need to take extra care.QuoteAgreed. They are not lightweight enough for embedded development on the more resource-limited microcontrollers that we use with Oberon e.g those with only 32 Kb of RAM.QuoteAgreed++ Explicit qualification of imported module references is a key part of this. Initially it can seem like a PITA but they make life soooo much easier when maintaining code. Those new to programming would not have experienced this. Once you realise that the effort required for software that is designed to last is 10-20% development and 80-90% maintenance it gives you a very different perspective ;-)

author: hamster_nz
author_rank: Super Contributor
timestamp: July 22, 2021, 10:46:42 pm
content: Quote from: tggzzz on July 22, 2021, 09:55:43 pmAnd here was I thinking about how nice COBOL was because the internal data representation matched what is useful to the user, not what is optimal for the computer:Code:01 SALES-INPUT-DETAIL.05 SALES-NUM-IN PIC 9(4).05 SALES-NAME-IN PIC X(20).05 SALES-REGION-IN PIC 9.05 QUOTA-CLASS-IN PIC X.05 COMM-CLASS-IN PIC 9.05 YTD-SALES-IN PIC 9(6)V99.05 YTD-RETURNS-IN PIC 9(5)V99.05 CURR-SALES-IN PIC 9(5)V99.05 CURR-RETURNS-IN PIC 9(4)V99.05 FILLER PIC X(25).01 SALES-REPORT-DETAIL.05 FILLER PIC X(7) VALUE SPACES.05 SALES-NUM-OUT PIC 9(4).05 FILLER PIC X(5) VALUE SPACES.05 SALES-NAME-OUT PIC X(20).05 FILLER PIC X(5) VALUE SPACES.05 SALES-REGION-OUT PIC 9.05 FILLER PIC X(10) VALUE SPACES.05 QUOTA-CLASS-OUT PIC X.05 FILLER PIC X(10) VALUE SPACES.05 COMM-CLASS-OUT PIC 9.05 FILLER PIC X(5) VALUE SPACES.05 YTD-SALES-OUT PIC $$$$,$$9.99.05 FILLER PIC X(5) VALUE SPACES.05 YTD-RETURNS-OUT PIC $$$,$$9.99.05 FILLER PIC X(5) VALUE SPACES.05 CURR-SALES-OUT PIC $$$,$$9.99.05 FILLER PIC X(5) VALUE SPACES.05 CURR-RETURNS-OUT PIC $$,$$9.99.05 FILLER PIC X(9) VALUE SPACES.Wouldn't C be nice if you didn't have to muck around with stupid printf format specifiers...

author: tggzzz
author_rank: Super Contributor
timestamp: July 22, 2021, 11:28:41 pm
content: If printf format specifiers are your major problem with C, then either you are an expert or you don't know how little you know

author: brucehoult
author_rank: Super Contributor
timestamp: July 22, 2021, 11:55:41 pm
content: Quote from: Siwastaja on July 22, 2021, 07:32:11 amWhat disallows reordering?

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2021, 12:08:38 am
content: Quote from: brucehoult on July 22, 2021, 11:55:41 pmAt least one thing AFAIR: the "address" of the first member of a struct must be equal to the address of the struct itself. IIRC, so please correct me if I'm wrong. So at least the first member could not be reordered.Meaning:Code:struct { int n; .... } S;&S shall be equal to &S.n, if I'm not mistaken.Edit: checked in the standard. The following is pretty explicit:QuoteEdit2: if you're unconvinced the above strictly requires struct members to follow order of declaration (I'll admit it's not completely clear), there's a hint in that the last member of a struct can be a "flexible array" member. It's obvious that such a member could not be reordered. That was in C99...In C11, things get clearer (so I guess the committee realized older revisions were not fully clear about it):QuoteAs things are, the C standard can't change this. This would break existing code all over the place.If it introduced the possibility of reordering struct members by compilers, it could be done adding a specific qualifier next to the struct definition, so that wouldn't break existing code. Now of course, you would not be able to use the flexible array thing with this. It would have to be explicitely checked by compilers.I wouldn't mind having this possibility of relaxing member ordering indeed, that would give compilers opportunities to optimize alignment and total size and would minimize required padding.

author: hamster_nz
author_rank: Super Contributor
timestamp: July 23, 2021, 12:30:07 am
content: Quote from: tggzzz on July 22, 2021, 11:28:41 pmMy beef (if I really had one) would be that all the basic data types are computer-friendly, not user/application friendly.If I want to hold all 6-digit positive integers I need to use a uint32_t or equivalent. What's wrong with 3 bytes of BCD? Even the 6502 had a BCD mode!Or how about support for for fixed-point binary representations? The compiler should have no trouble doing the bookkeeping.This is why I always think that C99 'complex' data types feels wrong. I mean it is a good idea, and it enables lots of performance enhancements and nice coding, but it doesn't feel like C. It has way too much sophistication about it for C.Oh, and IMO printf() format specifiers do suck - for example, it is most likely a university-level assignment to correctly print out an integer with commas. But scanf() format specifiers suck twice as hard, so much that I usually resort to writing my own parsers for anything but quick hacks.

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: July 23, 2021, 01:06:30 am
content: Quote from: brucehoult on July 22, 2021, 11:55:41 pmThe fact that the language supports relative pointer comparisons for members of the same aggregate object, including structs. A pointer to a field declared "earlier" in the  sequence of fields shall comparelessthan a pointer to a field declared "later".Code:int main(void){struct S { int a,b; } s;&s.a < &s.b; // <- this comparison is well-defined and shall evaluate to 1}From a very abstract point of view this can be satisfied through "compiler magic" even with reordering fields, but the practical reality says that this means that fields cannot be reordered.

author: brucehoult
author_rank: Super Contributor
timestamp: July 23, 2021, 03:52:08 am
content: Quote from: tggzzz on July 22, 2021, 09:50:40 pmWhat changed?You can *almost* write a threading library in pure and reasonably portable C using setjmp and longjmp (or sigsetjmp / siglongjmp).The difficulty is that to create a new thread you need to change the stack pointer (and maybe PC) inside a jmp_buf but it's an opaque structure (different on every CPU type of course) so there is no standard safe reliable way to do that.

author: james_s
author_rank: Super Contributor
timestamp: July 23, 2021, 06:03:08 am
content: Quote from: Ed.Kloonk on July 22, 2021, 10:54:45 amPython is primarily a scripting language, it's an interpreted language that is designed to be quick and easy to implement but it is not really suitable for embedded development. Yes there is Micropython but nobody is going to use that for serious embedded work.

author: brucehoult
author_rank: Super Contributor
timestamp: July 23, 2021, 06:22:45 am
content: Quote from: james_s on July 23, 2021, 06:03:08 amNot every "embedded" application requires microsecond or even millisecond performance. And many microcontrollers now have speed and capacity comparable to our desktop computers in the 80s.As an aside, it amuses me when someone reviews a i3 or Atom computer and says "It's ok for light use but you wouldn't want to run Photoshop on it".Dude. We used to run Photoshop on 33 MHz machines with 8 MB RAM and thought we were lucky.

author: westfw
author_rank: Super Contributor
timestamp: July 23, 2021, 07:59:58 am
content: I would be a lot happier with C if it had a decent native “string” data type and operations.Although that would significantly increase the minimum size of the runtime footprint (which is currently close to zero…)

author: DiTBho
author_rank: Super Contributor
timestamp: July 23, 2021, 08:52:39 am
content: C + strings = phpNot good, but not too bad after a full training.

author: bd139
author_rank: Super Contributor
timestamp: July 23, 2021, 09:02:50 am
content: Not quite.PHP = C + strings - pointers + crack smoking crazy.

author: paf
author_rank: Regular Contributor
timestamp: July 23, 2021, 10:53:05 am
content: There are times when C is the right language, when Python is the right language, when PHP is the right language, when Assembly is the right language, etc...But to use C (or any other language) in an effective manner, you need to know the "quirks" of the language and use it with the right set of tools.To use a nail you need a hammer, and to use a screw you need a screwdriver.Using C without tools like Valgrind (like bd139 has said), cppcheck or splint is not using C.It is "programming by poking".

author: tggzzz
author_rank: Super Contributor
timestamp: July 23, 2021, 11:04:04 am
content: Quote from: paf on July 23, 2021, 10:53:05 amThe 1980s equivalent was "cc is half a compiler; the other half is lint"

author: bd139
author_rank: Super Contributor
timestamp: July 23, 2021, 11:24:13 am
content: To point out one flaw in paf’s comment: PHP is never the right language. That’s like using a marrow to hammer in nails. The nails keep winning. Apart from that I agree with the rest of the comment

author: DiTBho
author_rank: Super Contributor
timestamp: July 23, 2021, 12:06:30 pm
content: Python is too slow for scripting on a Ath5 machine clocked at 180MhzPerl is good, but my productivity with Perl is very badBash-scripting is a valid option, but dictionaries are not supported(here is where I have to write C-modules to help bash, which means ... I have to hack the bash)php already comes with string support, json dictionaries, and even networking capabilities---> php looks the right tool for the job

author: bd139
author_rank: Super Contributor
timestamp: July 23, 2021, 12:12:11 pm
content: Go is the right tool for the job there. It does all of those and farts out one compiles static linked binary. And isn’t PHP

author: DiTBho
author_rank: Super Contributor
timestamp: July 23, 2021, 12:24:46 pm
content: Go is very good, but in my case is a bad choice because its main-implementation depends on llvm/Clang, which is hard to be cross-compiled for PowerPC, SH and MIPS.It's mostly profiled for mainstream architectures, mostly x86 and Arm.The Ath5 SoC has a mips32-r1-be core, when I tried to make Go running on it ... I found thousand problems that I don't frankly want to deal with because my purpose is not "to fix Go on mips", but rather making the ath5 to work for my applications.

author: paf
author_rank: Regular Contributor
timestamp: July 23, 2021, 12:31:49 pm
content: Quote from: bd139 on July 23, 2021, 11:24:13 amThinking better, I agree with you...

author: bd139
author_rank: Super Contributor
timestamp: July 23, 2021, 12:41:35 pm
content: Quote from: DiTBho on July 23, 2021, 12:24:46 pmOk that's a completely fair point. I still wouldn't us PHPIn that case I'd use Python and profile it. The slow or ballooning memory bits would get rewritten in C.If you think of Python as a tool for sticking bits of C together then it works for that.

author: DiTBho
author_rank: Super Contributor
timestamp: July 23, 2021, 12:54:17 pm
content: Quote from: bd139 on July 23, 2021, 12:41:35 pmGood idea, maybe for the next stageAfter all, months ago, I replaced my CASIO Casio FX-9860GII with a Casio FX-9860GIII mostly because the GIII runs ucPython, which needs to be hacked to support inline assembly.The TCP/IP stack to connect ucPython to the lan is written in C. It's based on ucIP, addressed to the serial-link, and encapsulated into a kind-of-serial at 115200bps.ucPython + inline assembly + C = power and elegance

author: PlainName
author_rank: Super Contributor
timestamp: July 23, 2021, 03:17:37 pm
content: QuoteCode:printf("%s", BCD3bytes2asc(*bcdvar));

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: July 23, 2021, 03:26:33 pm
content: Quote from: paf on July 23, 2021, 10:53:05 amNope. If you are a competent C programmer, "cppcheck or splint" works naturally in your head.As for valgrind - this is a valuable tool, but a tool for the integration team. Programmers don't use valgrind, unless stuck panicking in a completely desperate situation.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2021, 05:27:47 pm
content: Quote from: DiTBho on July 23, 2021, 08:52:39 amI had never seen PHP compared to C in any way or form until this.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2021, 05:52:14 pm
content: Quote from: cfbsoftware on July 22, 2021, 10:34:45 pmOh, I would like to give an extensive answer to this to do Oberon fair justice. So, sorry if this is short and simple. Also, do not hesitate to tell me where I could have been wrong - I think I know Oberon fairly well, but obviously not nearly as well as you do. So I'll just give a few points off the top of my head:- Keywords are all uppercase, and the language is case-sensitive. Uppercase keywords really annoy me and my fingers. They were justified back in the days when text editors didn't have syntax highlighting, but these days, they are just a major annoyance IMHO.- Constants (CONST section) are typeless. They are essentially like macros. That bothers me. Not a huge dealbreaker, I admit, but I'd like typed constants. I know you can always declare variables, initialize them in the "body" of the module, and use them as constants, but they are not proper constants as they could be modified, at least within the module.- Related: you can declare variables and make them private to a module, but you can't make variables constant (AFAIR, please correct me if I'm wrong). So, I think that's a limitation.- Point I'm not 100% sure of: there are no array or record initializers. So initializing them is very clunky compared to other languages.- Usually not much of a problem for embedded development (but Oberon is a general purpose language), but a bit more for higher-level stuff: there are no dynamic arrays. Wirth actually removed them from Oberon-2 IIRC. C doesn't have anything like this either, and you have to implement them by hand, but it would have been nice to have them in Oberon.- Related, dynamic memory allocation is all based on a garbage collector. I don't reject GCs in all cases or as a principle, but I think it could be nice if it could alternatively use a static allocator instead.- Something C was long plagued with as well: there are no fixed (and standard)-width integers. No unsigned integers in general either, except for the BYTE. So IIRC, you have BYTE (which should be an 8-bit unsigned integer on most platforms), and INTEGER, which is a signed integer. The width depends on the platform. If you need to define and/or access integers with a specific width, look elsewhere... you may have to resort to the SYSTEM module. Now see below as well.- Probably a lot of other shortcomings I can't think of at the moment.Quote from: cfbsoftware on July 22, 2021, 10:34:45 pmWell, for embedded development, you really can't do without this. Register access requires SYSTEM. Likewise and related to above: actually accessing memory with a defined width (such as 8-bit, 16-bit, 32-bit, etc) is impossible to guarantee without proper procedures in the SYSTEM module. Otherwise you're restricted to BYTE and INTEGER. The width of which is uh... not necessarily what you need for a given access, and unfortunately for portability, platform- and implementation-dependent. I don't completely mind having to use a dedicated module for this low-level stuff. But I do mind a little bit that the SYSTEM module may have to implement different functions and procedures depending on the platform, and that there's no standard way of accessing memory with a given width.Anyway, don't take this as Oberon bashing at all. I think it's a nice language, but, and in particular the latest Oberon-07, it is an exercise in simplicity and I do think Wirth went too far with it (he clearly removed everything he could while keeping the language usable, nice but sometimes too much). I gave a few examples, I'm sure there are lots of others. But that said, it can certainly be used as an alternative to C. I'm just explaining here (shortly) why I personally think it's not quite fit for this. My own opinion.

author: bd139
author_rank: Super Contributor
timestamp: July 23, 2021, 06:46:26 pm
content: Quote from: TheCalligrapher on July 23, 2021, 03:26:33 pmI disagree. Valgrind should be used continually to ensure you haven’t created yourself something that is expensive to fix later. All problems are yours until proven otherwise.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 23, 2021, 06:53:01 pm
content: Quote from: bd139 on July 23, 2021, 06:46:26 pmYeah. Guess what. However competent you are, your head is fallible. Static and dynamic analysis tools help you catch whatever mistake you may have inadvertently made. Someone thinking they never make any mistake because they are so competent is deluded.Now of course tools shouldn't be a replacement for your brain. They are just there to complement it. So using those tools because you don't know what you're doing is, certainly, not going to work that well. But even experts make mistakes.

author: DiTBho
author_rank: Super Contributor
timestamp: July 23, 2021, 07:44:15 pm
content: Quote from: bd139 on July 23, 2021, 06:46:26 pmyou : Valgrind = me : ICE

author: bd139
author_rank: Super Contributor
timestamp: July 23, 2021, 08:31:04 pm
content: Ideally me = FORTH but no one wants that

author: james_s
author_rank: Super Contributor
timestamp: July 23, 2021, 08:33:33 pm
content: Quote from: brucehoult on July 23, 2021, 06:22:45 amThat's entirely true of course, but my experience playing with Micropython is that it's fun and a great replacement for something like the BASIC Stamp but it's not the most stable platform I've used and you end up needing a 32 bit ARM to do what could easily be done on an 8 bit microcontroller. It's a neat toy, but there is no reason to use an interpreted language to do embedded development, the less than perfect stability alone is reason not to. I have microcontroller projects I made that have been running for over 20 years and I've never had any of them crash or stop responding, they all run bare metal with no operating system at all. An interpreted embedded language is an operating system in itself and there is a lot of stuff going on under the hood that I can't see or control.And yes, I remember running Photoshop on a 33MHz 486 and a 25MHz Mac and it was great, but Photoshop then and Photoshop now are two entirely different things. For a casual user like me the old one would probably still be adequate, but at the time I was using it a 640x480 image was high resolution. Now my photographer friend is regularly working with 12+ megapixel raw images. The hard drive on those old machines I used isn't big enough to hold them, much less the RAM.

author: brucehoult
author_rank: Super Contributor
timestamp: July 23, 2021, 11:48:42 pm
content: Quote from: james_s on July 23, 2021, 08:33:33 pmIt was capable of a bit more than that :-)I remember my clients using 68k Macs (which topped out at the 40 MHz Quadra 840AV) to routinely touch up 3000x2000 scans of 35 mm negatives (using a huge scanner that cost well into six digits -- you smeared the neg (or slide) with a transparent gel with a carefully controlled refractive index then taped it to a glass drum).From time to time I got called into debug a 500 MB PostScript file that would not print. I used BBEdit to open / search / edit it -- on a machine with just a few MB of RAM. I remember using Perl for analysis also as soon as it became available on the Mac.For a time I offered a service doing custom half-toning using some unique shapes and techniques a colleague and I developed. I would get a 300 DPI CMYK TIFF image of an A4 or A3 page and convert it to four 3387 DPI bitmaps. That's about 39600 x 28000 or 132 MB for each separation for A4. I could open those in Photoshop to check them on a 60 MHz PowerPC 601.

author: tggzzz
author_rank: Super Contributor
timestamp: July 24, 2021, 12:29:42 am
content: Quote from: TheCalligrapher on July 23, 2021, 03:26:33 pmYou have a narrow definition of "programmer"; not all programes are written in the way you appear to be inferring.I suspect you believe you are far more capable than the vast majority of C programmers. An attitude like yours is hubris, which is traditionally followed by nemesis - with the results we see in CERT advisories

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: July 24, 2021, 01:34:12 am
content: Quote from: bd139 on July 23, 2021, 06:46:26 pmContinually is fine. I'm just saying that "continually" means that QA/integration team runs valgrind onregularbasis as part of their QA routine. And the issues found by valgrind are then passed back to the R&D for fixing or annotation. Many modern valgrind-like tools (as well as static anaysis tools) are deliberately designed to fit that purpose.As for using valgrind as everyday debugging tool, as in "I don't know what's causing the problem and I'm too lazy to approach it directly, so I'll just run valgrind and hope that it finds the right culprit for me" - this is just a loser's way out.Of course, not everybody works in an environment that provides such a clear-cut separation of responsibilities between teams, but still... valgrind is a periodic housecleaning tool, not an everyday debugging tool.

author: westfw
author_rank: Super Contributor
timestamp: July 24, 2021, 01:45:56 am
content: QuoteAh. The heart of the matter. C isn't so much a "language" as at least three different languages:Portable Assembler C. "Libraries are irrelevant because they all suck anyway. I want to write my own bare metal manipulations, and anything that interferes with that is evil."Embedded C. "I've only got 128k-2MB of program space and 32-256k of RAM, but it might be nice not to have to write my own USB stack."Desktop C. "The whole problem space is pretty trivial compared to the resources I have, but I really want to avoid security bugs."High-level C: "I'm working on a hard problem, and I want a compiler that makes it work as well as inhumanly possible!"Computer-Science C: "I want an elegant way to express fancy algorithms in readable style."(FIVE different languages!!)(arguably, there have been lots of attempts at "Desktop C" replacements, and the usual ivory-tower "no one actually uses that in the real world" attempts for "Computer Science C")For instance (from the valgrind homepage):QuoteIt's been a long time since I cared much about 6 of those... And I think the last time I cared about four of the others was on such a non-standard system that they would have been of limited use.)(BTW: My impression is that modern C compilers include a lot of the error checking that you used to have to use things like lint to get. Is that not true?)

author: cfbsoftware
author_rank: Regular Contributor
timestamp: July 24, 2021, 03:52:14 am
content: Quote from: SiliconWizard on July 23, 2021, 05:52:14 pmThis would have to be the most common gripe I have heard. To me it is like somebody saying they wouldn't drive a Ferrari because they can't get it in any colour other than red.My typing isn't particularly good either and it was one of the major incentives for me to develop the Oberon-aware Astrobe IDE. One of its features is automatic capitalisation of keywords. You just continue typing in lowercase as normal and when it recognises the last word typed is a keyword it capitalises it for you. We've also catered for the rare occasions where you don't want this to happen and find it works extremely well in practice.Actually it would have been easier to have modified the compiler to accept lowercase keywords as well. There are several reasons why I believe a case-sensitive language and uppercase keywords can be useful:a) As long as you avoid all-uppercase identifiers you know you can use whatever word is the best choice for a particular variable.e.g. some of the following would be invalid in Pascal:Code:colour := black; type := digital; case := plastic;now := 2021; then := 1969;b) If you avoid using all-uppercase characters in your own identifiers your program will never be invalidated at some future time if, and when, new keywords are added to the language.c) The language designer has the freedom to select the most suitable keyword for a new feature rather than trying to avoid a word that is likely to break existing software.d) Syntax-highlighting might be useful when working on a screen but monochrome printed program text and code samples in books have yet to disappear altogether.e) Rather than using a Delphi-like convention of prefixing typenames with the letter T, or the horrendous Hungarian notation, you can use the Oberon convention of starting type names with a capital letter and variable names with a lower case letter:Code:list: TList;then becomes:Code:list: List;The thought of doing this can perplex Pascal / Delphi programmers who have had no hands-on Modula-2 / Oberon experience. It needs to be tried for a while before deciding whether you like it or not.QuoteI'm not sure that I follow you here. Floating-point constants are REAL, string constants are character arrays, numeric constants are INTEGER. You can't assign a constant to a variable of a different type.QuoteStand correctedExported variables cannot be directly modified in a client module. There would need to be a 'setter' procedure also declared in the exporting module to enable modification. The setter procedure could then do any necessary validation if required.QuoteTrue. However, it is rarely a problem in practice for me as I rarely, if ever, use array or record initialisers even when using languages that allow them. When reading code where the record or array would be complex / large enough to make it clunky to initialize it, I have a great deal of difficulty comprehending which part of the array / record an alternative constant initialiser maps onto. While I accept that it would be irksome to those who like such initialisers I would be surprised if it was considered to be a deal-breaker.QuoteTrue. However, I wouldn't recommend using Oberon-07 for anything other than embedded development. A programming language is a tool. Every competent programmer should understand the pros and cons of several languages and choose the most suitable tool for the task in hand. e.g. I use C# and Component Pascal (a superset of Oberon-2) for Windows GUI development such as the Astrobe IDE. I wouldn't dream of coding it in Oberon-07 any more than I would dream of coding it in C.QuoteA garbage collector is not mandated for Oberon-07. The Astrobe Cortex-M compilers have a safe, restricted, 'Dispose' function that works in a last-in / first out basis. Source code of the system's Memory Allocation module is available - it's only 80 lines of Oberon code so is easily understandable and modifiable.QuoteAn actual parameter declared as ARRAY OF BYTE can have ANY data type passed to it as long as it has the same size. You can then perform BYTE operations within the procedure. Although this is currently implemented in both the ARM Cortex-M and RISC5 FPGA compilers it is not yet defined in the Language Report so should currently be considered as a language extension. In Astrobe we also implemented built-in standard procedures BFI and BFX for bitfield insert and bitfield extract operations. These are extremely efficient on ARM Cortex-M processors because they directly use the corresponding BFI and BFX Thumb-2 instructions as inline code. Examples of this can be seen in the BitFields discussion on the Astrobe forum:https://www.astrobe.com/forum/viewtopic.php?f=3&t=564QuoteYes - you have covered most, if not all, of the common gripes. Every language has pros and cons. Much of the time these are subjective, Either the cons become insignificant over time or they become so bad that you swear never to use the language ever again. I won't mention any names ;-)QuoteNot at all. Thank you for your feedback. I very much appreciate the time and thought you have put into it.

author: bd139
author_rank: Super Contributor
timestamp: July 24, 2021, 08:22:41 am
content: Quote from: TheCalligrapher on July 24, 2021, 01:34:12 amNope. Valgrind should be an every day debugging tool. Static analysers as well. They stop your poor assumptions leaking into the integration suite where it’s harder to do a root cause analysis. You’re right that they’re not a substitute for thought but assuming your problem is someone else’s problem is one massive fault in most SDLC.Guess who’s job it is running the team who picks up smouldering craters from that assumption on a regular basis.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 24, 2021, 08:31:50 am
content: Quote from: bd139 on July 22, 2021, 06:32:26 pmWould be interested in hearing about the development time for the first case.

author: bd139
author_rank: Super Contributor
timestamp: July 24, 2021, 08:36:18 am
content: It took them about a month, mostly of meetings, two false starts and several pages of confluence content generated and of course pair programming. That actually replaced a massive chunk of C# which was running for several years and took several hours to run doing horribly inefficient queries against SQL server. That broke when someone fired up a PO for a bigger SQL box and someone said no.I will grant them the fact that they reverse engineered the C# thing in that time and bothered to write down what it was supposed to do which made my job easier.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 24, 2021, 09:50:43 am
content: Quote from: tggzzz on July 22, 2021, 08:16:11 pmQuite obviously, my comment was a simplification beyond being very useful.In any case, my point regarding RTOS is that people seem to expect that RTOS's abstractions solve the difficulties regarding parallelism and timing determinism easily, providing a silver bullet. This is far from being true. Especially in simple cases, the added weight is a hindrance.In a large, complex system, given very experienced developers and massive budgets, like at NASA, I'm sure using an RTOS instead of simple ad-hoc solutions above bare metal, is the right choice.

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: July 24, 2021, 10:12:06 am
content: Quote from: westfw on July 24, 2021, 01:45:56 amI think that one of the reasons why people tend to avoid using any standard library when using C as a portable assembler is that they were designed for being used and not for being ported. Being able to use printf to send messages through a serial connection (uart, i2c, etc) improves code portability and in some cases allows testing your program before having manufactured the prototype (if the standard library is used as a HAL and the rest of hardware dependent code is also encapsulated it is sometimes possible to test the program on a development board to test other parts of the circuit before having a prototype, which can be useful for debugging the high level part of the program). However, implementing the functions that need to be implemented usually depend on the compiler provided by the manufacturer, which usually is not precisely amazing.Having a “standard HAL” could help changing that mindset, as that would mean that you need to provide an implementation for a well defined api to be able to use the standard library instead of some obscure compiler dependent functions. Nevertheless, some functions of the standard library that rely on having an operating system (like executing a command in the system shell) would still not be used, mainly because they aren’t needed in those applications (which doesn’t mean that they are not useful in other environments nor that they shouldn’t be available as part of the standard library, just that those particular applications don’t need it)

author: tggzzz
author_rank: Super Contributor
timestamp: July 24, 2021, 10:29:26 am
content: Quote from: Siwastaja on July 24, 2021, 09:50:43 amAgreed, except that I'd argue that ateamof non-wizard programmers might be well advised to use an RTOS. It will providea framework for guiding the high and low level designsdemarcation boundaries between subsystems and programmerslogging (and debugging) facilities so you can see what is actually happeningThose points are not so advantageous to an individual programmer working on small applicatons, of course.

author: DiTBho
author_rank: Super Contributor
timestamp: July 24, 2021, 12:24:42 pm
content: Quote from: westfw on July 24, 2021, 01:45:56 amUseful to pass any theoretical computer science exam, and even to express any algorithm like if it was an abstract mathematical fancy, perhaps even to describe the world without the need to have the time variable in its inner equations (which is the new frontier of physics and math) ... but, just, like it happens with some classes of Turing machines, the other side of the coin is that its implementation won't conclude its computation in any finite time.

author: bd139
author_rank: Super Contributor
timestamp: July 24, 2021, 12:47:18 pm
content: On that note, it’s amazing how many computer scientists I see using various associative abstract data types (hash tables etc) with only two items in them. Oh for the purity.

author: tggzzz
author_rank: Super Contributor
timestamp: July 24, 2021, 02:42:50 pm
content: Quote from: bd139 on July 24, 2021, 12:47:18 pmTheir counting scheme is probably (and quite reasonably!): zero, one, many.

author: bd139
author_rank: Super Contributor
timestamp: July 24, 2021, 02:46:47 pm
content: Certain aboriginal people had that numbering system too.

author: tggzzz
author_rank: Super Contributor
timestamp: July 24, 2021, 03:05:23 pm
content: Quote from: bd139 on July 24, 2021, 02:46:47 pmThe Australian aboriginies also have a different, fascinating perception of the world. To indicate where something is, they don't say "behind you" or "on your left", they say "north east of you" or "south".

author: DiTBho
author_rank: Super Contributor
timestamp: July 24, 2021, 03:51:53 pm
content: Quote from: tggzzz on July 24, 2021, 02:42:50 pmthat's exactly how functional languages require to thinkzero -> empty listone -> first element of the listmany -> remaining elements in the list

author: bd139
author_rank: Super Contributor
timestamp: July 24, 2021, 03:59:37 pm
content: And C. Linked list struct containing pointer to next item and pointer to data. And lisp to some degree with car cdr etc.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 24, 2021, 06:03:57 pm
content: Quote from: cfbsoftware on July 24, 2021, 03:52:14 amI'm sure it is, and I can see why. I don't quite agree it's just a simple matter of taste, although it's certainly partly this.Again, I would fully understand how this would make the code a lot more readable in the absence of syntax highlighting. But otherwise, it's annoying. Even reading it is annoying (but OK, that part alone is a matter of taste I guess.) As to typing, sure you can implement tricks in text editors to make up for it, but I frankly hate editors that would "auto-correct" things while I type. It's extremely annoying, and I know many people agree. I never enable anything like this in my text editors. I never enable auto-completion on the fly either. I hate things popping up when I'm typing. I set up a key shortcut for auto-completion when I need it. All this is absolutely not major of course. Just a little gripe. But the way a particular language appears on screen is important for readability IMO, and certainly we probably all have a different way of considering readability.Quote from: cfbsoftware on July 24, 2021, 03:52:14 amMaybe I didn't express it fully clearly. What you are talking about are *literals*. Every prog. language has a way of writing literals. But in CONST section, those are not linked to a type.I guess the fact you don't see a difference is because of Oberon's simplicity which has only very few basic types (especially integers as I mentioned), no array literals, and so on, so that the type can always be unambiguously derived from the literal, but that's not always the case in languages for which there could be ambiguities.Quote from: cfbsoftware on July 24, 2021, 03:52:14 amYes, but not within a module itself. I guess it all boils down to the point about CONST above. But I'll give you an example: since Oberon doesn't allow array or record literals, they can't be CONST. So you can't have a constant array or record within a module itself. It is a limitation IMO.Quote from: cfbsoftware on July 24, 2021, 03:52:14 amMany people do. It's much more compact that initializing members/items one by one with an assignment. C has solved the member "ambiguity" for structs since C99, you can pass the member identifier like: "{ .x = 1, .y = 2 }". It's compact and readable.One somewhat related point is that to make up for it, developers in Oberon (and similar languages), following what Wirth was himself doing, tend to put several statements on the same line. So with the example above, they will usually just write: "S.x := 1; S.y := 2;" and call it day. I for one have a rule of never putting more than one statement on a single line. I think it hinders readability, and that's something that for me makes a lot of Oberon code hard to read. Statements all over the place. Of course you're not forced to doing this. But I just don't like this style, and having no initializers for arrays and records will kind of push this style.One way having no initiliazers ("literals") for arrays and records is a real issue regarding the point I made above with constants. You can't declare a constant array or record. Yes you pointed out that outside of a module, exported arrays or records will essentially act as constants, but not within the module itself. This can be problematic. You can argue that you may put all your "constants" in a separate module, and that would solve the issue. Which woud be fair enough, if making things a bit harder than needed.I won't get into more details for dynamic allocation, but just saying the model is still limited for general-purpose use, and as we're talking about a replacement for C, there's not reason not to consider dynamic allocation. And, it seems that the ability to use a non-GC allocator in your implementation is an extension of Oberon. The report doesn't mention anything like this AFAIR.Quote from: cfbsoftware on July 24, 2021, 03:52:14 amThis is interesting, but not part of the original language report. You have acknolwedged it was lacking, and added this as an extension. Like your non-GC allocator. I'm sure you have added a few other extensions as well, for instance for dealing with interrupts. So, see, you were forced acknowledging some things were lacking in the language. Now all things I've mentioned here would likely be pretty simple to add/modify in the language as well. It would just not be the exact language defined in the report...As to integers, I still think there are things missing. Not having integers of various widths makes certain kinds of arithmetics difficult or clunky. Having only BYTE and INTEGER doesn't quite cut it IMO. Not that you can't circumvent this, but it's a bit limiting.Quote from: cfbsoftware on July 24, 2021, 03:52:14 amWell, this is a thread about thinking of a replacement for C, and I mentioned Oberon while saying it wasn't quite there, so obviously that meant I thought there were things missing. Still, I suggest anyone at least curious to have a look at Oberon.Oh, and as said here, you have already implemented a number of extensions. Possibly adding a couple others would make it even better. That was my point.Now apart from the few things I talked about, and that could be seen as "details", there's something more drastic.Some people (many these days actually) do think modern programming languages should include built-in constructs for dealing with "parallel multitasking" (multi-threading if you will), some of those people are in this thread. But Wirth was convinced of the opposite. C is obviously lacking anything regarding this, but that's part of what many people think it's seriously limited. So if you're one of those people, you would have to consider this for any potential language replacement.

author: DiTBho
author_rank: Super Contributor
timestamp: July 24, 2021, 09:08:16 pm
content: Quote from: SiliconWizard on July 24, 2021, 06:03:57 pmIf you need a practical target of reference, look at the Epiphany-V, for instance the version with 1024-cores.Programming it in C has already demonstrated to be limited and very prone to catastrophic results

author: brucehoult
author_rank: Super Contributor
timestamp: July 25, 2021, 12:22:46 am
content: Quote from: SiliconWizard on July 24, 2021, 06:03:57 pmThis is an obvious problem in embedded, as you'd have no way to get initialised constant data structures into ROM. They'll need to be stored in RAM, and set up at program startup by code in ROM -- code that is several times bigger than the data they're initialising.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 25, 2021, 12:43:17 am
content: Quote from: brucehoult on July 25, 2021, 12:22:46 amThat too. Now I'll wait for cfbsoftware's reply on that; they may have added specific extensions/behavior to their compilers to allow doing exactly this - maybe at the link step.In Oberon, modules have a "body" in which you can typically put code for initializing them - which would be where you'd put the code for initializing constant arrays and records for instance. I guess the compiler/linker can relatively easily detect which variables are only set in the module body and never modified outside of that, and then automatically put them in an appropriate section of memory. I'm curious to know if this is what cfbsoftware have implemented.But in any case, the language itself - at least without extensions - cannot directly describe variables that are indeed constants. So I'm saying this can be usually inferred, but not directly expressed by the developer.

author: DiTBho
author_rank: Super Contributor
timestamp: July 25, 2021, 08:57:21 am
content: I saw a C-like compiler made by a Japanese company that adds three new keywords:in,out,inoutWhen you write a function, you can use one of these keyword to describe if the variable issomething that can only be read, therefore a constant (in)something that can only be written out as result (out)something to be read in and modified back (inout)Anyway, this only tells the function how to behave with parameters, but i do find it clear and elegant.It would be cool ifin,out,inoutcould be used in a typedefCode:typedef long in const_uint32_t;typedef long inout uint32_t;typedef char in const_char_t;const_char_t msg[]="hello world, I am actually a true constant, nobody can touch me";This way it could also be super easy to write a linkerscript that allocate all the "in" variables to the constant pool section.

author: gf
author_rank: Super Contributor
timestamp: July 25, 2021, 09:33:56 am
content: QuoteI don't see the point. If you defineconstchar msg[]="hello world, I am actually a true constant, nobody can touch me";then (by default) msg is placed in the .rodata section anyway (which is baisically the constant pool). No proprietary annotation is required for that.

author: brucehoult
author_rank: Super Contributor
timestamp: July 25, 2021, 10:30:11 am
content: Quote from: DiTBho on July 25, 2021, 08:57:21 amAda did exactly this, 40 years ago.

author: DiTBho
author_rank: Super Contributor
timestamp: July 25, 2021, 10:46:01 am
content: QuoteAs well as an architecture analysis and design tool does to design projectsWhen engineers design and plan a project with AADL/Hood, both C and Ada projects are defined in the same way regarding their interfaces, thus I guess for the Japanese company I visited in 2014 it was a "natural" choice, since they use these tools on regular basis.

author: tggzzz
author_rank: Super Contributor
timestamp: July 25, 2021, 10:53:09 am
content: Quote from: brucehoult on July 25, 2021, 10:30:11 amIt isn't far off being a truism that academic papers on C/C++ rarely cite other languages, whereas academic papers on other languages refer to many languages. Several conclusions could be drawn, none particularly flattering to the C/C++ community.

author: DiTBho
author_rank: Super Contributor
timestamp: July 25, 2021, 10:56:09 am
content: Quote from: gf on July 25, 2021, 09:33:56 amIt's more clear to read and coherent if also applied to function parameters as well as global constants.It allows to specify write-only registers, and as bonus, it's also directly compatible with AADL/Hood tools.

author: gf
author_rank: Super Contributor
timestamp: July 25, 2021, 02:05:53 pm
content: I meant, already now (w/o introducing in, out, inout) you can write a linkerscript that allocates all constant variables in a constant pool section.Subjectively, I find the termsin, out, inoutintuitive for function parameters, but not so intuitive for global variables. You are obviously used to AADL/Hood tools, while I and possibly other are not. But at the end the name of the keyword is just a matter of definition, of course.Currently there is indeed no way to define write-only variables in C. But a regular variable which is only written, but never read, is virtually useless. Why should a variable be written, if its value is ignored anyway? Eventually it would only make sense in conjunction with C extensions which map C variables directly to hardware registers of peripherals. Or as type qualifier (analog toconstandvolatile), in order that e.g. lvalue expressions referring to peripheral registers could be tagged write-only.

author: DiTBho
author_rank: Super Contributor
timestamp: July 25, 2021, 02:45:25 pm
content: Quote from: gf on July 25, 2021, 02:05:53 pmThe ICEs we use have some memory mapped registers, for instance the debug_console_out is a write only memory mapped register, as well as a lot of peripherals made by Motorola and Freescale.If you try to read from those registers, the manual say the hardware behavior is not guaranteed, but practically the ICE goes mad and you have to force an hardware reset.And it's the point when you hammer your head on the wall:oh, see, the code has been compiles correctly, just ... d'oh, at line-x I forgot it was a write-only register.---> face palm and embarrassThis info is also exported to the ICE itself, so if you don't tell it to not read at location x, soon or later it will, unless you spend time to manually edit the symbol list, or post process them with sed, both procedures which somehow work, but they prone to consume time and introduce errors.The WDT of the 683xx as well as the WDT of the PCE500 is like that. Don't try to read from any write-only register, or hell will look into you.

author: paf
author_rank: Regular Contributor
timestamp: July 25, 2021, 03:59:05 pm
content: Quote from: gf on July 25, 2021, 09:33:56 amIf you only want a string constant, this will do:char * msg="hello world, I am actually a true constant, nobody can touch me";

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: July 25, 2021, 04:16:07 pm
content: Quote from: gf on July 25, 2021, 09:33:56 amUm... Formally/pedantically it is not entirely accurate.What you have on the right-hand side is a string literal. It is a non-modifiable nameless object of array type (which can and will be normally placed in .rodata, yes). BTW, in C it is a `char ` array, not a `const char ` array: even though it is non-modifiable, its type is not const-qualified that way. Just a C-specific historical oddity.What you have on the left-hand side is an ordinary named const-qualified array `msg`, which is (can be) located in "regular" memory. That array `msg` is initialized by the string literal bycopyingdata from the string literal to the array.In other words, conceptually you have two separate objects here, not one: a string literal and an array `msg` holding its copy.The rest is work of an optimizer in a real-life implementation. The optimizer correctly concludes that there's no need for two separate objects in this case and just one is enough: instead of copying the string literal iinto `msg` the compiler simply "maps" `msg` directly onto the string literal (in .rodata).---If one'd want to avoid the need for this conceptual transformation, one'd used the following insteadconst char *const msg = "hello world, I am actually a true constant, nobody can touch me";

author: gf
author_rank: Super Contributor
timestamp: July 25, 2021, 04:16:28 pm
content: Quote from: DiTBho on July 25, 2021, 02:45:25 pmI mean, for "regular" program variables (in RAM, only accessed by the CPU, and not shared with any peripherals) it is virtually useless.I did not deny the usefulness for memory mapped registers of peripherals, which are indeed write-only sometimes.An alternative (in order to prevent accidental read access) were of course, to hide the definition of the debug_console_out register from all modules of the program, and to provide an accessor function, (say) write_debug_console_out(....) which needs to be called. Then only the write_debug_console_out() function needs to take care.Quote from: paf on July 25, 2021, 03:59:05 pmButmsgis not an array variable then, but a pointer, andmsgis not a constant variable either.And letting a char* variable point to a string literal (which has type const char*) is not clean either (though usually still accepted by C compilers).A "clean" definition of a constant pointer to a constant string were rather:Code:const char * const msg = "hello world, I am actually a true constant, nobody can touch me";

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 25, 2021, 04:22:07 pm
content: Quote from: brucehoult on July 25, 2021, 10:30:11 amThat's also something you can find in Component Pascal IIRC (and, I think the earlier Modula-2 and -3).As I said earlier in the thread, actually Ada has pretty much everything most people have asked for in this thread. If again there were a lighter language based off Ada and with much relaxed runtime requirements, I would go for it in an instant.I've seen Nim, inspired by Ada (and related languages), which didn't look too shabby.https://nim-lang.org/They unfortunately had the very bad taste of picking a syntax à-la Python. That's enough to instantly trash it.Also, I don't know how fit it would be for embedded development, haven't looked closely enough.

author: PlainName
author_rank: Super Contributor
timestamp: July 25, 2021, 04:34:15 pm
content: QuoteAnd in the 'get to know it' documentation provide an excellent example of the issue, perhaps unwittingly:Code:while guess != number:raw_guess = readLine(stdin)if raw_guess == "": continue # Skip this iterationguess = str.parseInt(raw_guess)if guess == 1001:echo("AAAAAAGGG!")breakelif guess > number:echo("Nope. Too high.")elif guess < number:echo(guess, " is too low")else:echo("Yeeeeeehaw!")

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 25, 2021, 04:44:10 pm
content: Quote from: gf on July 25, 2021, 04:16:28 pmIt's even worse than just being "accepted". It will yield no warning, neither with GCC nor with Clang, even with -Wall and even with adding -pedantic.But there is worse.Code:void Test(void){char * msg="hello world, I am actually a true constant, nobody can touch me";*msg = '\0';}Yes, GCC will accept this without a single warning. Not just that; it will actually put the string literal in the .rodata section, where indeed it's meant to belong...And the generated code actually writes a zero to the first byte.Of course this piece of code sucks and a competent programmer will avoid something like this. But still, this could happen in more subtle cases and that's where static analysis tools can be handy.For instance, cppcheck on this piece of code yields:Code:Test4.c:3:15: error: Modifying string literal "hello world, I a.." directly or indirectly is undefined behaviour. char * msg="hello world, I am actually a true constant, nobody can touch me";^Test4.c:4:5: note: Modifying string literal "hello world, I a.." directly or indirectly is undefined behaviour.*msg = '\0';Note that this is one of C's oddities - where "undefined behavior" sucks. This is a case of UB, so most compilers will just shut up and let you shoot yourself with an UB.OTOH, if you write:Code:void Test(void){const char * msg="hello world, I am actually a true constant, nobody can touch me";char * msg2 = msg;}You'll get a proper warning for the second assignment. Because this case is not UB. You like this already?Quote from: gf on July 25, 2021, 04:16:28 pmYes, as TheCalligrapher said above.

author: DiTBho
author_rank: Super Contributor
timestamp: July 25, 2021, 04:57:54 pm
content: Quote from: SiliconWizard on July 25, 2021, 04:22:07 pmYup, I know what you mean, 15 years ago I tried to develop a ada crosscompiler for hc11; it worked on the top of gcc-v3.4.*, but I had to relax the run-time requirements and as result .. it was just Ada-sugar.Better than nothing, but practically ... a toy. Sorry

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: July 25, 2021, 05:23:50 pm
content: Quote from: gf on July 25, 2021, 04:16:28 pmTrue.Although you can also do this:Code:char (*const msg) = &"Hello World";This `msg` is rather unwieldy in subsequent use, but it does declare a "pointer to an array", which preserves the "arrayness" of the pointed object.And, unfortunately, const-correctness rules of C will not allow you to declare it as `constchar (*const msg)` (another historical oddity).Quote from: gf on July 25, 2021, 04:16:28 pmThat is incorrect. As I already stated above, a string literal in C has type `char `. Firstly, it is not a pointer, it is an array. Secondly, it isnotqualified by `const`. (In C++ it would be, but not in C.)So, the result of array-to-ponter decay applied to a string literal in C is `char *`, not `const char *`. It is not something "usually" accepted by C compilers, it is a hard rule of the language.

author: tszaboo
author_rank: Super Contributor
timestamp: July 25, 2021, 06:03:14 pm
content: ;, **, print("%20.5s\n", str);, callbackpointers, cmsis, vendor libraries, returning more than 1 parameter, atoi, pointerstopointers, side effects, asshats who intentionally program their code for side effects, unsafe typecasting, no (a,b) = (b,a), accessing data in a struct which is passed as a pointer, operator precedence, goto, if(a=b) is always true with no warning, calling int as int32_t to be able to port some code into a 8051 (just in case), and so on.I hate C. I don't want to code C anymore ever in my life.Just no. You don't have enough money to make me do it.

author: gf
author_rank: Super Contributor
timestamp: July 25, 2021, 06:10:01 pm
content: Quote from: TheCalligrapher on July 25, 2021, 05:23:50 pmSorry, typo. the type of a string literal is of course an array, not a pointer.But you are right, in C it is not const (I mixed up with C++, here it is const).https://en.cppreference.com/w/c/language/string_literalThen I'm indeed wondering why the compiler places the string literal in .rodata?

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 25, 2021, 06:16:13 pm
content: Quote from: gf on July 25, 2021, 06:10:01 pmWell well well...Thanks to the infamous UB. The standard says: "If the program attempts to modify such an array, the behavior is undeﬁned."Since modifying arrays formed by string literals is UB, compilers are free to assume they are read-only. So, this is what most compilers do. But, since they are not 'const', the read-only characteristic is not enforced at the source level. So, no warning. (Except again with decent static analyzers.) This makes perfect sense, but it's not particularly pretty.

author: gf
author_rank: Super Contributor
timestamp: July 25, 2021, 08:26:27 pm
content: IMO the C++ definition, where the type of string literals is const char[], makes more sense, when attempts to modify the array are UB anyway.Edit: I wonder whether the non-const string literals are still a leftover from K&R C, which did not yet have "const"?

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: July 25, 2021, 10:12:48 pm
content: Quote from: gf on July 25, 2021, 06:10:01 pmEven though the type of string literal is not `const`, the literal is still officiallynon-modifiableand therefore can be placed into the read-only data segment.The type is not `const` just for compatibility with legacy versions of the language.C++ also maintained this compatibility (with C) in the first version of C++ standard: even though in C++ string literals are `const` arrays, in C++98 they were still implicitly convertible to `char *` pointers. This unusual conversion was deprecated from day one. It has been discarded from the language in C++11.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 27, 2021, 04:51:19 pm
content: Quote from: DiTBho on July 24, 2021, 09:08:16 pmWhat's the typical language used for programming this then?

author: DiTBho
author_rank: Super Contributor
timestamp: July 27, 2021, 07:10:24 pm
content: Quote from: SiliconWizard on July 27, 2021, 04:51:19 pmprecisely the two main questions it leads to:Which is the best parallel programming language for initiating undergraduate students in the world of parallel computing?OpenCL can be used in a variety of multicore systems and growing, but is it a good candidate?I don't knowI program my Epiphany-V cores in eRlang, but I have heard some guys having good results with "C=", aka "C Stripes", a C-like but Parallel Programming Language designed with a couple ofextensionson the top of the traditional "C language" to cover all typical parallel programming paradigms and complement or even substitute existing parallel language extensions and libraries by providing a single parallel language most naturally connected with the C-like syntax and semantics.

author: Bassman59
author_rank: Super Contributor
timestamp: July 27, 2021, 07:18:37 pm
content: I'm quite happy to look at other languages. An example: Swift on macOS. it's a pretty neat language. (A lot is hidden in the run-time ... kinda like Ada, huh?) I thought Objective-C with its message-passing idiom was pretty neat. Rust looks interesting. And like most people reading this, I dabble in Python for quick test code and whatever.But for actual work, which for me is embedded microcontrollers and FPGAs, I'm wholly uninterested in new languages. Wake me when, for example, a vendor has a full-up Rust environment that works as well as the C stuff they provide. That is: libraries, debuggers, example code, the whole of it.And for FPGAs, whatever new languages someone might be creating are useless until Xilinx, Intel/Altera and Synopsys have full-up synthesis support and Xilinx and ModelSim have full-up simulation/verification support. None of this generating-intermediate-Verilog stuff.

author: DiTBho
author_rank: Super Contributor
timestamp: July 27, 2021, 07:33:51 pm
content: Quote from: Bassman59 on July 27, 2021, 07:18:37 pmFPGAs don't need anything else, just VHDL and Verilog (perhaps also SCALA, which outputs VHDL and Verilog)

author: brucehoult
author_rank: Super Contributor
timestamp: July 28, 2021, 01:06:53 am
content: Quote from: Bassman59 on July 27, 2021, 07:18:37 pmSwift is pretty cool. It's also open source and available on all the major desktop OSes --- for example swift.ord has pre-packaged toolchains for Swift 5.4.2 dated June 28 2021 for MacOS, Ubuntu 16.04, 18.04, 20.04, CentOS 7 & 8, Amazon Linux 2, Windows 10.QuoteI'm similar. For small systems I'm really only interested in C and assembler. And only in ISAs that have gcc and/or llvm support.I could stretch that to other languages that use gcc or llvm optimiser and back end, and don't need a significant runtime library.QuoteI have to disagree there. It's the moral equivalent of a higher level language compiling to portable C. That's a perfectly fine strategy and I've used many of them (and written a couple).

author: brucehoult
author_rank: Super Contributor
timestamp: July 28, 2021, 01:12:10 am
content: Quote from: DiTBho on July 27, 2021, 07:33:51 pmScala doesn't output VHDL and Verilog.Certain *libraries* written in Scala output VHDL and Verilog. In fact Chisel outputs FIRRTL, which is similar to LLVM IR, and also can go through a variety of optimisation passes before eventually being converted to VHDL or Verilog.Also, MyHDL and PyHDL (maybe others too) use Python in the same manner as Chisel and SpinalHDL use Scala.

author: Bassman59
author_rank: Super Contributor
timestamp: July 28, 2021, 07:04:22 am
content: Quote from: DiTBho on July 27, 2021, 07:33:51 pmThey don't, but that doesn't stop people from trying to come up with something "better."

author: bd139
author_rank: Super Contributor
timestamp: July 28, 2021, 07:18:42 am
content: Quote from: brucehoult on July 28, 2021, 01:12:10 amJust to add on that, we bought out a company that wrote half their stuff in Scala. We are currently rewriting their product in "not Scala" and they have tears of joy because it was their number one mistake apparently.Interestingly yesterday I had to MacGyver some shit up extremely quickly to replace an infrastructure component (from Microsoft) which failed under load testing. Now usually I'd probably attack this problem in C as it's suited to the application here which is roughly suck up UDP packets, parse and relay to stdout. But I needed some protection against back pressure which is quite difficult with C. You end up either having to do everything with select which is a pain in the butt. Add to that the fact I didn't have time available to make any memory management mistakes and needed portability between Windows and didn't want to write it on Windows to start with because that's just painful, I picked Go.I had the job done in 90 lines and 90 minutes. Hosted on macOS/arm64 with binary outputs generated for Linux/amd64 and Windows/amd64. Target nodes sinking 350,000 UDP packets a minute at 3% CPU passing sustained load test.That is now a better "C". They reduced time to market, ability to shoot your toes off and made cross compilation a joy.

author: DiTBho
author_rank: Super Contributor
timestamp: July 28, 2021, 10:00:51 am
content: Quote from: Bassman59 on July 28, 2021, 07:04:22 amand me to ignore them

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 28, 2021, 04:15:17 pm
content: Quote from: Bassman59 on July 28, 2021, 07:04:22 amWhile I myself said that I wouldn't use one of those "higher-level" HDLs and would stick to the standard ones for a number of reasons, I'll still honestly admit that it has proven to work in some cases. SiFive has been successful using Chisel and I don't think they have a plan to switch back to Verilog or VHDL any time soon. (Now if Intel does acquire SiFive as was being discussed, things may change, but also as we discussed, Intel's main reason for buying SiFive if they ever do may not be directly reusing their cores anyway...)

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 28, 2021, 10:40:32 pm
content: So... this one is fun:https://sysdig.com/blog/cve-2021-33909-sequoia-falco-linux-filesystem/Note that enabling proper warnings/using static analysis on this (and of course caring about LOOKING and fixing the issue) would have avoided the bug.The f*cking -Wconversion flag should be enabled by default when using -Wall in GCC. Really. I have already talked about how I always enable it.I have actually never issued static analysis on the Linux kernel source code (never contributed either), but I'd be curious to do just that.

author: DiTBho
author_rank: Super Contributor
timestamp: July 28, 2021, 11:27:14 pm
content: Probably scheduled for kernel v6 or v7. At the moment I see a lot of code regressions, which means that old friends of bugs that should have already been defeated go back to saying "hAllo again".Any comment about "C="?

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 28, 2021, 11:43:09 pm
content: Quote from: DiTBho on July 28, 2021, 11:27:14 pmI took a quick look and didn't see anything particularly interesting in that, I mean compared to alternatives. Is there a compiler for this?I had looked at Cilk, years ago.https://en.wikipedia.org/wiki/CilkCilk influenced OpenMP, and GCC has been supporting OpenMP for many versions now, so I think OpenMP would be the more standard alternative. I've used it only a little bit so far. "C=" may just look like it has a bit better syntax sugar coating, but otherwise, the same functionalities are there in OpenMP. Don't hesitate to tell me what C= would do better (again apart from syntax), as you may be more familiar with it than I am.

author: Bassman59
author_rank: Super Contributor
timestamp: July 29, 2021, 05:49:20 pm
content: Quote from: SiliconWizard on July 28, 2021, 04:15:17 pmI startedhere. I found and spent some time reading throughThe Chisel Bookand ... I don't see where Chisel is better than VHDL or SystemVerilog. Honestly. The syntax is different. The book also has an odd statement:Quote"Generate hardware" must mean "generate a table that gets synthesized into a ROM." Because other than that, I've never written a Python script to generate hardware! I honestly don't know what is meant by that statement.The main Chisel page has a link to a Stack Exchangearticlefull of sound and fury, but signifying nothing, as it doesn't actually answer the question posed.One of the things that seems weird to me is that it has a notion of an implicit clock for registers. Many FPGA designs have multiple clocks, and it is really handy to know which clock is driving which elements! And it would be interesting to see an example of how to manage clock-domain crossings in Chisel.I don't see how Chisel allows for instantiation of black boxes for FPGA features like deserializers and other I/O things, clock management blocks and the like. Perhaps someone has written libraries which present those features as modules you instantiate, and there's some magic under the hood that manages this?Does Chisel support parametrized design and generics and the like? Can I instantiate multiple copies of a lower-level entity like I can in VHDL with a generate loop? I have some designs here which has a "channel" entity which can be replicated simply with such a loop.I'd like to see an example of a small but complete hierarchical FPGA design written in Chisel. The design should include lower-level entities/modules/whatever as instantiated in the top level. Some of those lower-level things should themselves instantiate even lower level things.Anyway. I'm honestly open to learning about why Chisel/Scala could be better. But for my designs, which tend to be kitchen-sink collections of stuff with a bunch of external peripherals which need servicing, I don't see the advantages.

author: madires
author_rank: Super Contributor
timestamp: July 29, 2021, 06:19:53 pm
content: This discussion reminds me of a classic xkcd:https://m.xkcd.com/927/

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: July 29, 2021, 09:00:19 pm
content: Quote from: Bassman59 on July 29, 2021, 05:49:20 pmAlthough I haven’t found an official procedure for sending comments to the vhdl standard committee as the one that exists in the case of ada (http://www.ada-auth.org/comment.html), it seems that they use a wiki and a git lab repo for that purpose (http://www.eda-twiki.org/cgi-bin/view.cgi/P1076/WebHome). Therefore, if being able to use hardware-generators (instructions for generating specification tables from a higher level language) was the only reason for creating Chisel, sending a feature request to the committee might have been easier than implementing a whole new languageDon’t get me wrong, I’m not saying that Chisel is a bad thing. It’s just that adding new features to an existing language seems to require less work

author: SL4P
author_rank: Super Contributor
timestamp: July 30, 2021, 12:53:13 am
content: Having scrolled through this thread, it confirms my own thoughts and beliefs…I started with C about 30 years ago, and glad I’m still using it.There’s enough capability in C to do almost anything, especially on low spec hardware.I’ve written one small Python project for a friend, and know that the ‘benefits’ are nowhere the waste of time.I dropped interpreted languages with BASIC.

author: bd139
author_rank: Super Contributor
timestamp: July 30, 2021, 08:00:56 am
content: Your comment doesn’t scale well. The moment you need more complex data structures, parsing or network communications you’ll still be fixing bugs in yours while the python guys have finished their project and are sipping cocktails on the beach.

author: Siwastaja
author_rank: Super Contributor
timestamp: July 30, 2021, 08:29:07 am
content: Quote from: bd139 on July 30, 2021, 08:00:56 am... because someone wrote the implementation in C, and the "Python guys" instantiated that.

author: bd139
author_rank: Super Contributor
timestamp: July 30, 2021, 09:14:58 am
content: Correct.Python is just a quick way to glue bits of C together

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 30, 2021, 05:12:24 pm
content: Would be nice if the thread could get back on track, though.HDLs, Python...?Next thing you know, people are going to start talking about Javascript. Yeah, no.

author: Bassman59
author_rank: Super Contributor
timestamp: July 30, 2021, 09:21:59 pm
content: Quote from: SiliconWizard on July 30, 2021, 05:12:24 pmI think part of the reason for thread drift is because there's a realization: how many patches can you apply to C before it's no longer C? And if that's the case, then why not start with a different language built from the ground up to address the issues? This latter point is why we see Swift taking off (pushed in no small part by the Cupertino Fruit Company) and Rust seems to be getting some interest.Python doesn't solve any of C's problems, nor does Java.As for HDLs, well, I'm sure everyone who does both VHDL and C has written this kind of thing in C and wondered why the program didn't work:Code:if( foo /= bar) {doSomething();elsedoSomethingElse();}

author: bd139
author_rank: Super Contributor
timestamp: July 30, 2021, 10:03:50 pm
content: Quote from: SiliconWizard on July 30, 2021, 05:12:24 pmThis is all I have to say on that subject.

author: tggzzz
author_rank: Super Contributor
timestamp: July 30, 2021, 10:16:25 pm
content: ... Or get somebody else to do it.JavaScript is to browsers as C is to MCUs -a lowest common denominator intermediate language.

author: bd139
author_rank: Super Contributor
timestamp: July 30, 2021, 10:28:09 pm
content: It’s not even that. It’s a tar pit to lure ex PHP developers into so they can’t harm anywhere else.The funny thing about PHP was that it was ultimately supposed to be a safer way of writing CGI scripts than C but wasn’t Perl. Hmm.

author: DiTBho
author_rank: Super Contributor
timestamp: July 30, 2021, 10:33:38 pm
content: I am playing with gcc v1-beta on a MINIX-v1 VirtualMachine (1) in order to compiler Linux v0.0.1WOW, everything was so different, the CC compiler and C sources don't look "C".Weird emotions, memories of the 90s, but it really looks alien compared to modern C on modern Gccedit:(1) in i386 emulation mode

author: tggzzz
author_rank: Super Contributor
timestamp: July 30, 2021, 11:38:34 pm
content: Quote from: bd139 on July 30, 2021, 10:28:09 pmIn that case I guess it succeeded and was beneficial. Caveat: I've always run away from pushing web pixels, and awk is as near as I've got to Perl. Neither will ever change.

author: bd139
author_rank: Super Contributor
timestamp: July 31, 2021, 07:42:43 am
content: It’s sticky tape and string and hacks end to end. The fact we built half of our modern culture on it makes it difficult for me to sleep some nights.Back on topic, I think all the C replacements have failed because they aren’t C. There is no way to replace it. It’s just right in all the right places and just wrong enough where you need it to be.Also I hope Rust burns. That’s just a whole new world of problems.

author: gf
author_rank: Super Contributor
timestamp: July 31, 2021, 08:23:06 am
content: Quote from: DiTBho on July 30, 2021, 10:33:38 pmBtw, didn't early versions of Minux use Tannenbaum's ACK compiler (Amsterdam Compiler Kit), and not yet gcc?

author: DiTBho
author_rank: Super Contributor
timestamp: July 31, 2021, 09:47:00 am
content: Quote from: gf on July 31, 2021, 08:23:06 amyup, the ACK has been used as the standard Minix compiler for years, but this was done by distributing binaries, when sources get opened, a version was forked off and used as part of the Minix base buildand, but I found a note written by Richard Stallman telling the generated code quality like was - he said -Honestly? Not great- so I wanted to somehow bootstap a beta version of the first GNU CC and use it on Minux-v1 to compile the first version of the kernel Linux.Fancy configs, and I honestly wouldn't expect it too much; v0.0.1 was pretty much a demonstration || proof-of-concept. It really doesn't do so much, there is no rootfs, there is a note to add a first process but it sounds like a short C programs that prints out "Linus Rulez!" and exits with a delicious kernel panicCode:Linus Rulez! ... Kernel panic, attempted to kill init!LOLThe Finnish keyboard is hard-wired in kernel/keyboard.s (yes, in assembly) and cannot be changed without major problems, but the kernel/*.c files are there and the CC compiler is what I careAnd but look at these comments:Code:Oh, the things people do to avoid casts. Shame it'll break with gcc'sSome people are morons. Do not use sizeof!...some things never change

author: Siwastaja
author_rank: Super Contributor
timestamp: July 31, 2021, 01:09:26 pm
content: Quote from: tggzzz on July 30, 2021, 10:16:25 pm... Kind of yes, but with the exception that C has a proper standard, and 99% of programming is per that standard, and compiler extensions are well known and play a minor role. And sometimes, you can choose to write non-portable C "by design", having control over the whole system.Whereas, Javascript is a moving target and standardization body has accepted they have lost the battle and just have to document how the code behaves in different browser versions. And Javascripthasto be portable, you can't make a mistake limiting the usability across browsers. And Javascript kinda forces you to "test reliability into product" as you would say, there is no way to prove a certain code just works. In C, that is not easy either but at least remotely possible or almost there!

author: DiTBho
author_rank: Super Contributor
timestamp: July 31, 2021, 01:58:01 pm
content: What I love ( or hate? ) about C is that sometimes the code looks so horrible that nobody cares to read it carefully, and I still remember what happened in in January 1999, when the source distribution of Socat was found hacked with a trojaned version of TCPWrappers which basically did the followingget a socket opendup(stdin, stdout, stderr) to the socketexecve /bin/shin short, it opened a remote shell, and this allowed the intruder access to any server that it was installed on, and that's was funny because TCPWrappers is a host-based networking ACL system, used to filter network access to Internet Protocol servers on Unix-like operating systems such as Linux.So, it was the defensive system that literally left the door open, and the source code was under the nose of everyone, but since C sucks in being "clean and tidy", nobody cared to give a look at the source code compiled and executed with the root privileges(1), until - "oops, I think there are some intruders entered the network ..."LOL(1) today we have category privileges, distro like Arch-Linux massively encourage to use them.

author: tggzzz
author_rank: Super Contributor
timestamp: July 31, 2021, 03:16:46 pm
content: Quote from: Siwastaja on July 31, 2021, 01:09:26 pmBased on that description, I'm struggling to see the difference between C and JavaScript

author: Siwastaja
author_rank: Super Contributor
timestamp: July 31, 2021, 04:05:27 pm
content: Well youcanwrite C that perfectly conforms to the standard, and compilers produce portable code*. It is maybe a tad more difficult than it needs to be, but so is heart surgery. It ispossiblefor a mentally capable engineer like many on this forum, for example.*) real world always have bugs, every non-trivial language and compiler has bugs. C compilers are pretty good overall.Same cannot be said of Javascript, which is always a massive battle and requires very practical "I hope this works in 95% of cases and will test the most common ones and iteratively adjust until barely satisfied" mindset.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 31, 2021, 05:16:36 pm
content: Quote from: bd139 on July 31, 2021, 07:42:43 amWhereas several decades of use have shown the last sentence looks right, I just can't fathom "there is no way to replace it". Although most attempts have failed indeed, nothing in this world, at least things that are man-made, is a definitive absolute. So this can't be right. K&R were certainly extremely well inspired, but they were no gods.Quote from: bd139 on July 31, 2021, 07:42:43 amAhah, I guess we like your (often) extreme tone.If it turns out not to be fit for long-term real use, then it will die by itself. No need to curse it.I think there's a number of good ideas in Rust. And a fair deal of bad ones. All topped up with an overall atrocious syntax (but that's relatively subjective here). My first reaction to Rust was fairly negative, but not willing to have too much prejudice, I still took a close look. I liked some things, such as 'traits'. I did not really like the whole borrowing thing. While looking good on the surface, I think it turns out to be a very wrong answer to a real problem. As to syntax, while it remotely looks C-like, it's in all its glory odd enough that it makes any real Rust code almost unreadable unless you've been thoroughly "initiated". Then all this crates stuff has good and bad. It's not all rosy. But the worse part is that many of the programmers that are trying to use it to develop real things with it, even when they have a couple years of experience with it, still struggle.Anyway, yes. Replacing C is hard. It's surely not impossible though. For any chance of success, I think it'll take a lot of pragmatism, and it'll take listening to people actually developing things, rather than designing a brand new language with a small team convinced they know how things should be done.

author: bd139
author_rank: Super Contributor
timestamp: July 31, 2021, 05:19:44 pm
content: Quote from: DiTBho on July 31, 2021, 01:58:01 pmTo be fair I spent a month chasing an issue in an asynchronous c# program a couple of years back. That was one fucking huge tangle which you couldn’t muster if you tried. The issue was that the continuation ended up with someone else’s context which you can imagine in fintech is a “holy fuck” moment which is difficult to recover from. Much fewer bodies than rockets, cars and medical equipment but an order of magnitude more lawyers and auditors.The issue was eventually traced to a simple typo in an extension which caused an occasional race condition on a lock (a wtf in itself) and the continuation to resume with the wrong context.Devices which are used to help us understand programs and scale them are as much footguns as bad code.I try at least to leave the world in a better state where possible. Some people however don’t give a monkeys.

author: bd139
author_rank: Super Contributor
timestamp: July 31, 2021, 05:39:14 pm
content: Quote from: SiliconWizard on July 31, 2021, 05:16:36 pmYou’re right about pragmatism. K&R were pragmatists and acknowledgists (more on that in a minute) and definitely not gods. The last term I invented about 20 years ago and roughly it suggests that they acknowledge that human and machine interfaces are a compromise always. This is roughly based around the concrete parameters of time, money and available technology. They overdelivered with C.This is long forgotten which is why we have these no compromise toolchains appearing. And on that note; Rust. Agree with your points.My problem with Rust is that it’s written by C++ programmers. If you’re going to write something from scratch you need clean room thinking. This is incidentally why I never got anywhere with writing languages - I have too much exposure to them and tend to design a fucked up mutant like Rust. Where I tend to win is DSLs but no one has noticed yet they they are all shoddy Lisp implementationsMy favourite one was a basically the scheme engine from SICP ported to C and dynamically loaded into a python program to run a 500 line pattern matching engine. I know better now.

author: SiliconWizard
author_rank: Super Contributor
timestamp: July 31, 2021, 06:39:57 pm
content: Rust was initially a one-person project, so it very much falls into the category I talked about. The guy was a Mozilla employee. How Mozilla got interested in this enough to invest and give him a team, I don't know for sure. I'd sure be curious to know the whole internal story.

author: tggzzz
author_rank: Super Contributor
timestamp: July 31, 2021, 08:45:46 pm
content: Quote from: Siwastaja on July 31, 2021, 04:05:27 pmFTFYQuoteIf you listen to the language lawyers, C compilers are bug free; it is always the programmer's understanding of (one of) the standards that is buggy.

author: brucehoult
author_rank: Super Contributor
timestamp: July 31, 2021, 11:31:49 pm
content: Quote from: SiliconWizard on July 31, 2021, 06:39:57 pmI don't know the whole story, but I was there around that time. I joined the Mozilla Javascript team at the start of 2009 and left pretty much exactly a year later. Graydon was my official onboarding mentor and had been working on Rust for a couple of years already then. It was announced to the world in mid 2010.Rust was definitely a one-man project when I was there.How did Mozilla decide to do Rust? The same way they did anything. They had so much money they didn't know what to do with it, and would let an employee do pretty much anything that sounded like it might be good for humanity, the open source movement etc.Mozilla annual revenue in millions ... around 85% of it from Google search referral:2008: $ 792009: $1042010: $1232011: $1632012: $3112013: $3142014: $4202015: $4202016: $5202017: $5622018: $436There were 250 employees when I was there, so about $400k revenue per employee (and no other significant expenses except the office) and growing rapidly.Sounds idyllic, right? Unfortunately, it had the most extreme office politics I've ever seen.

author: DiTBho
author_rank: Super Contributor
timestamp: August 01, 2021, 01:07:53 am
content: Rush is not too bad

author: Siwastaja
author_rank: Super Contributor
timestamp: August 01, 2021, 06:49:59 am
content: Quote from: SiliconWizard on July 31, 2021, 05:16:36 pmOf course Ccanbe replaced. C isn't exceptionally good, many existing attempts to replace it could technically replace it if needs to be; if not straight away, then with some minor modifications that would come as a result of people starting using them to replace C usage. (Similarly tooriginalpre-C89 C without any compiler extensions etc. would be pretty crappy to modern day needs.)It's not about whether itcanbe replaced, it's about if itneedsto be replaced.But because C works well enough, why bother? The replacement would need to be exceptionally good and solve all the problems of C without introducing any new ones to be worth the hassle, and even then it would be difficult to make existing C programmers change because they are relatively happy with the status quo.But remove C by force, for example by outlawing it, and you'll see itcanbe replaced.

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: August 01, 2021, 07:13:24 am
content: Quote from: Siwastaja on August 01, 2021, 06:49:59 amAdditionally, rewriting programs that already work costs money. Most companies wouldn’t translate their old software to a new language unless something forces them to do it. However, new modules might be written in it, progressively displacing the old one, but rewriting everything from scratch is usually too costly to be accepted

author: Karel
author_rank: Super Contributor
timestamp: August 01, 2021, 08:06:55 am
content: Just a wake-up call. Every x years there's a new language that will replace C.For better or worse, C is still here and is not going anywhere. So, I'll stick with C.It just works everywhere and gets the job done.Regarding security, only few companies have security as their prime goal.The rest doesn't care as long as the product sells.Release quick, fix bugs later (if ever).As a side note, I believe that the only way to increase the quality of embedded software, is to remove the possibilityof software updates. This will force a company to test longer and better.In other words, treat software as hardware.

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: August 01, 2021, 08:37:50 am
content: Quote from: evb149 on August 01, 2021, 07:36:07 amHaving those things included in the standard would be nice. Nowadays that devices with ARM are becoming a common thing outside the embedded world, those problems are extending to general software development (trying to build a portable code that behave equally in all devices is not so trivial, especially if it needs to show anything in the screen as some OS as Android don’t even provide a shell able to show a printf). Cross platform development is becoming important (the number of react native and flutter users is increasing significantly), so it might be a good moment to submit a proposal to the standard committee.However, I haven’t found any information about how they should be submitted, but I wouldn’t expect it to be too different from C++ submission procedure (https://isocpp.org/std/submit-a-proposal) or, in the best case, it might just require sending the proposal to a mailing list as it happens with Ada

author: brucehoult
author_rank: Super Contributor
timestamp: August 01, 2021, 10:16:00 am
content: Quote from: evb149 on August 01, 2021, 07:36:07 amYou interpret the description backwards.It's not that C has every feature in every assembly language.It's that every feature in C maps efficiently to pretty much any sane ISA.C assumes and acknowledges that from time to time you'll need to link in an assembly language routine, or use some inline asm.How big are char, short, int, long? The same size as in the target ISA.How are signed integers represented? The same as on the target ISA.How do shifts involving signed quantities behave? The same as on the target ISA.Can you load a multi-byte type from an unaligned address? If and only if the target ISA can.You have to know all that stuff anyway if you program in assembly language. C doesn't add to that. C just frees you from having to do detailed instruction selection and register allocation and managing temporary values.If you *need* integers of a known size then you can specify those with uint8_t, int_least32_t and friends. If you want an integer that a pointer can be converted to and from without loss you have uintptr_t. And so on. I don't know of any other language that allows you to express your actual needs so precisely. Maybe Ada?Rotates? Bit reverse? CLZ? Popcount? Parity? Set/Clear a bit at an index? Plenty of ISAs don't have some or all of those. If C provided those as built-ins then you'd probably assume they were as efficient as an add though they're not. Better to make you aware some of those are going to require a dozen or two instructions."something SUPER SIMPLE like detect flags relating to arithmetic / logical operations" -- the majority of microcontroller and Linux boards I have in this house DON'T HAVE FLAGS.

author: DiTBho
author_rank: Super Contributor
timestamp: August 01, 2021, 10:50:41 am
content: Quote from: Siwastaja on August 01, 2021, 06:49:59 amC can be replaced and it will be. It has already reached its limits and we go on with a lot of troubles, but as until we work with 4-8 cores, we go on with gritted teeth, with more than 32 cores it becomes rather a bloody hell.The Linux kernel is another example. Yes, we have it, yes it has worked for 20 years, but ... if you look at how the code is maintained, and if you consider the complexity of the new kernel line v6 ... C doesn't help at all, C++ doesn't help at all, we need something better.And Rust is probably the choice.

author: bd139
author_rank: Super Contributor
timestamp: August 01, 2021, 11:17:20 am
content: I think we need to rethink the problems rather than come up with new solutions for the same problems. You mention parallelism as a deal breaker for C which arguably can be a problem. But a new language doesn’t necessarily solve those problems merely reshape them.Hence my earlier point about clean room thinking. tggzzz will nod to this one but it belongs in the computer science domain. Think Hoare’s CSP paper. My first implementation of that for me was using pipes and stdio with a C program that had no concept of threads at all.The language is rarely the problem. The environment and the thinking is.

author: PlainName
author_rank: Super Contributor
timestamp: August 01, 2021, 11:43:45 am
content: QuotePerhaps that's its attraction: it is small enough to be entirely grasped by most programmers, yet remains a very sharp tool. It is the PH2 screwdriver of languages. Hex heads and star drives are great if someone else has done the work, but try putting an appropriate indent in a custom screw you just made.

author: tggzzz
author_rank: Super Contributor
timestamp: August 01, 2021, 12:14:04 pm
content: Quote from: bd139 on August 01, 2021, 11:17:20 amYes indeed, wit the proviso that a language can make it more or less practical to think and express high level design cleanly and unambiguously.

author: DiTBho
author_rank: Super Contributor
timestamp: August 01, 2021, 12:39:56 pm
content: Quote from: bd139 on August 01, 2021, 11:17:20 amC allows too many hipster bad habits.New language, new bad habits, but also new fresh air, and new good habits.

author: bd139
author_rank: Super Contributor
timestamp: August 01, 2021, 01:08:56 pm
content: Play chess one piece at a time, not smash the board and buy a new one…

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 01, 2021, 04:56:04 pm
content: Quote from: brucehoult on August 01, 2021, 10:16:00 amAda definitely, in a much, much better way.But C is certainly a much simpler language requiring much simpler compilers. Which is a big plus in itself.

author: TheCalligrapher
author_rank: Regular Contributor
timestamp: August 01, 2021, 04:57:29 pm
content: Quote from: evb149 on August 01, 2021, 07:36:07 amC has often beenincorrectlydescribed as a "high level assembly language"by people who know little about C. FTFY.The only version of C that could be called "high level assembly language" without stretching it too much was the nascent version described in various versions of "C Reference Manual" in the 1970s (https://www.bell-labs.com/usr/dmr/www/cman.pdf).The very moment the K&R version came into existence, the idea of "high level assembly language" has been abandoned for good and forgotten.

author: DiTBho
author_rank: Super Contributor
timestamp: August 01, 2021, 05:25:02 pm
content: Quote from: TheCalligrapher on August 01, 2021, 04:57:29 pmthe compilers(1) I have on very old CP/M SBC boards(1) 1975-1989: Arnor C v1, Aztec C v1, BDS-C v1.6, Ecosoft C Compiler v3, HiTech C v3, HiSoft C v1, ManxC v1, Mi-C v3, Mix C Compiler v2, Q/C Compiler V3, SIL-Digilog v1, Small C v2, Supersoft C v1, Whitesmith C v2, Amsterdam Compiler Kit v1

author: DiTBho
author_rank: Super Contributor
timestamp: August 01, 2021, 05:33:31 pm
content: Quote from: evb149 on August 01, 2021, 07:36:07 amPrecisely the pointsAnd what aboutmonads? The lack ofmonadsis the reason why C needs gotos, and it's the reason why the critical sections of every OS looks a mess ... hard to understand, debug, and maintain.I want monads, please give me monads, I can have monads in a functional language like eRlang, but monads can be also implemented in every imperative language, so add monads to C!

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 01, 2021, 05:34:16 pm
content: Quote from: Karel on August 01, 2021, 08:06:55 amYes yes, I started right away saying this. Nobody needs to be waken up in this thread, I'm pretty sure.The main reason why C still sticks, apart from its own merits (and it has a lot of them obviously despite some of its shortcomings), is just that it's become industry-standard and is standardized. With actually a decent standard. Yeah, I know some may whine about it, but just take a look at the C++ standard, and come back. I think you'll see how good the C standard is after that quick adventure.The whole point of this thread was collectively figuring out what features could make C better without compromising any of its fundamental benefits. For this, I think we have gotten a few points that I'll summarize here (likely not exhaustive at all):- Better, more consistent arithmetics;- Partly related: no risky implicit conversions;- Much fewer, or ideally no undefined behaviors;- Modules;- Constrained types (such as ranges) - could also be used for bound checking when indexing arrays/buffers;- Tagged blocks, for easier and more consistent flow control;- Getting rid of the C switch with fall-through;Points about parallelism have been made, but as some have said, I'm not too sure having built-in support in the language would dramatically change things, part from sugar coating. It may make the developers' life a bit easier, but for a dramatic change, different computer architectures more adapted to parallelism should probably be devised first. Another thing to consider with this is that built-in support for parallelism almost inevitably implies offloading the nasty work to some runtime. It's kinda displacing the problem without fundamentally solving it.Of course another point was, as a corollary, to figure out what exactly would prevent any new language from taking off. The mere fact that those "are not C" partly explains this - see above - but there are oither reasons. As discussed earlier, one big problem is that most of those attempts have been lacking pragmatism, have essentially been one-person projects (so, way too opiniated approaches, lacking proper reviews of real-world practices), and have been much, much too complex. Yeah. If you wanna avoid the pitfalls of C++, do not fall into the same trap! Too complex languages with a bunch of programming paradigms stacked together are confusing, almost impossible to master, promote language fragmentation (which hinders maintenance), tend to make developers misuse them, make developing compilers a hell, the list is long...Yeah, Rust is nice, but IMHO it has fallen into this exact trap heads down.As to C++, I've found this "FQA" rather to the point:http://yosefk.com/c++fqa/index.html, and this can also trigger some thinking if you're ever considering designing a new language.

author: bd139
author_rank: Super Contributor
timestamp: August 01, 2021, 05:38:56 pm
content: You can write monads in C fine. Just you have to do some of the legwork that the higher languages compile away

author: DiTBho
author_rank: Super Contributor
timestamp: August 01, 2021, 06:11:06 pm
content: Quote from: bd139 on August 01, 2021, 05:38:56 pmYou can also writepolymorphismin C, and I usually do, but you have NO help from the C compiler, and this is the point!I want the compiler to help me!To havemonadsin C, you have to write polymorphic code, plus other stuff, and the result is ... ugly to read, also when I write polymorphic code, there is no "(inner) this" mechanism like in C++, therefore I need to pass p_this_t (void*) pointers among methods (which are not truly "methods" but rather pointers to special functions), also because the C language has no support for opaque pointers, no support for methods, and also no concept of module, and again ... it's possible to "implement them", I can even mimics modules and opaque pointers, I can do everything, butthe compiler is not helping me at all, and the code written this way is prone to contain bugs.The Linux kernel needs this stuff, and for a lot of reason Linus hates doing this stuff in C++, so ... it's like trying to drive a nail into the wall with a screwdriver rather than a hammer.We don't need all the bloated features offered by C++, just a couple of features, and for example Visual Pascal offers try {} catch {} error {} statements, which are close to monads and it's better than nothing.With full monads you can embedded the behavior within a datatype, and it's really great to have! Elegant, powerful, and it automatically makes the code more robust since a lot of programmers are so lazy they don't write all the code to cover the abnormal functioning in case of errors, because without native-monads you have to write many more lines of code. I can understand them.Seriously, I'd like to avoid to continuously hack the C compiler, I'd prefer to have native support.

author: Karel
author_rank: Super Contributor
timestamp: August 01, 2021, 06:31:58 pm
content: Quote from: SiliconWizard on August 01, 2021, 05:34:16 pmI understand it's interesting to talk about it, but we all do know that nobody is going to use this this informationand after another 20 years or so, C will still "rule"...

author: tggzzz
author_rank: Super Contributor
timestamp: August 01, 2021, 09:16:02 pm
content: Quote from: Karel on August 01, 2021, 06:31:58 pm... In the same way that COBOL still rules, I hope

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 02, 2021, 05:08:37 pm
content: Quote from: DiTBho on August 01, 2021, 06:11:06 pmYeah. Well, generally implementing "OO" stuff in C is doable (and I do this). It does require manual handling of many things, and sure you don't get any help from the compiler. OTOH, it doesn't necessarily require a lot more LOCs than a C++ equivalent. It just looks different, and you have approximately zero safety net.Quote from: DiTBho on August 01, 2021, 06:11:06 pmYeah. Monads? That can get pretty hairy. That's not something I would have considered adding to C. Drifting too far off there.Quote from: DiTBho on August 01, 2021, 06:11:06 pmI'd be interested in knowing exactly why the Linux kernel would need "monads". Can you elaborate on this and maybe give a couple examples?As to C++, I really suggest reading the "FQA" I linked to above. It's a relatively comprehensive analysis of the official C++ FAQ, taking answers and elaborating on them, often "debunking" them as well. After reading this, unless you're a die-hard C++ developer, you're likely to have a more definitive understanding of why many people "hate" C++, and why you probably shouldn't use it. You'll also get to see that many answers given in the official C++ FAQ are either ill-devised, or just dishonest. That also doesn't bode well IMHO.

author: DiTBho
author_rank: Super Contributor
timestamp: August 02, 2021, 07:30:26 pm
content: The Linux kernel is programmed like if it was object-programming but without object programming support, and all the exception points are manually encoded and usually expressed with "goto".Gotos are good and extremely efficient for critical sections, and they are not the problem, rather the reason why you need to write gotos is the problem: you write goto because the language has no support for the error propagation.With monads, you can define the abnormal behavior of something and embed it into a datatype, and the code will react like defined, you don't need to write any goto, you can plan and study the error propagation, and to do that you don't need to manually instruments the code to make sure you haven't forgotten something, it's rather the compiler that truly helps you.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 02, 2021, 10:47:26 pm
content: OK, thanks for the point.So, basically, what you would like is something to help with error handling. Indeed C is very "rough" with that, and error handling is almost always tedious and clunky.And, OTOH, exceptions have been proven not to be a very good answer to that in general.Problem with monads, as I see it, is that they really make sense only for a functional programming language. In particular, they reveal their potential when you heavily use function composition. C is not a functional language, and I don't think anyone would want it to become one. I've seen attempts at implementing monads in non-functional programming languages, and all were trying to indeed implement some kind of functional approach in a language not made for this. Often clunky, inefficient and inconsistent.Or maybe you have in mind something like monads in spirit, but adapted to a non-functional language. If so, I'd be curious to read you elaborate on it a little.Now the point of adding features to improve error handling, and do it better than exceptions, is duly taken anyway.

author: brucehoult
author_rank: Super Contributor
timestamp: August 02, 2021, 10:58:21 pm
content: Quote from: SiliconWizard on August 02, 2021, 10:47:26 pmNot sure I agree with that.I do agree that the way C++ and Java do exceptions sucks.I like much more the model where the handler is called *before* unwinding the stack, and has the option of resolving the problem and returning to the place the error occurred.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 02, 2021, 11:32:17 pm
content: Quote from: brucehoult on August 02, 2021, 10:58:21 pmWell, can you point me to a language that would, in your opinion, implement exceptions "right"?

author: brucehoult
author_rank: Super Contributor
timestamp: August 03, 2021, 01:40:24 am
content: Quote from: SiliconWizard on August 02, 2021, 11:32:17 pmDylan and its predecessor, Common Lisp.https://opendylan.org/books/drm/Conditionshttps://en.wikibooks.org/wiki/Common_Lisp/Advanced_topics/Condition_Systemhttps://gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html

author: JPortici
author_rank: Super Contributor
timestamp: August 03, 2021, 05:58:24 pm
content: Quote from: DiTBho on August 01, 2021, 01:07:53 amRush is awesome

author: DiTBho
author_rank: Super Contributor
timestamp: August 04, 2021, 09:19:26 am
content: Without monads that can trap errors before unrolling the stack, at least I would like C to force the user to always initialize a variable.Code:private p_char_t boolean_test_ans = { "failure", "success" };In this example one of my customers made a mess with my code by badly copying and past a procedure.As result, he forgot to initialize a variable to value False before the testCode:boolean_t test_result;if (...){test_result=....}printf("test %s: %s\n", test_name, boolean_test_ans);since test_result is only set inside the if () {} block, if the block is not executed test_result is not initialized, and as result it can assume randoms values.The result is catastrophic, because boolean_test_ans points to a random address in memory.The initialization of variables is a better practice, it should be mandatory !Code:boolean_t test_result=False;if (...){test_result=....}printf("test %s: %s\n", test_name, boolean_test_ans);Please add it to the list

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: August 04, 2021, 11:48:40 am
content: Quote from: DiTBho on August 04, 2021, 09:19:26 amBeing able to define a default value for specific types could also be a solution for that problem, as it avoids having to set an initial value for each variable, which would require to modify existing programs to be able to be able to compile them, while eliminating random behaviors

author: PlainName
author_rank: Super Contributor
timestamp: August 04, 2021, 12:37:41 pm
content: gcc, and I presume other compilers, will warn when this occurs. If this - setting a value on declaration - was mandated I would prefer to have it default to nul if nothing is specified. And for the compiler to continue to warn (that is, ignoring that it's defaulted to nul and treat it as uninitialised).

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 04, 2021, 04:18:04 pm
content: Quote from: brucehoult on August 03, 2021, 01:40:24 amThanks for the pointers. As with monads, it kind of looks like better exception/error handling is almost always found in functional languages.I do not know Dylan much (it seems like a weird multi-paradigm thing), but I don't think it would be a definite exception of this here, as it seems to have functional roots. (Incidentally, it seems to have been rather short-lived at Apple.) Didn't spend much time on it, but I admit I have a really hard time making sense of the language description so far.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 04, 2021, 04:26:55 pm
content: Quote from: Just_another_Dave on August 04, 2021, 11:48:40 amIt could look like a good idea. But I personally don't think it is here.In DiTBho's example, which is simple but rather typical, the right default value entirely depends on context. There is, in general, no particular reason that the default value should be any particular value.You may reply that this would be solved using type-bound default values as you suggested, but even then, here it would be a bad idea that looks good on the surface, IMHO. Again the right default value all depends on context, and could be different in different contexts. So in the end you would end up with one "type" per "context", which could become pretty cumbersome.Oh, and the idea that "zero" is a reasonable initial value for everything is a pretty weird one actually.Type-bound initial values can be great and have their uses, but not for error handling IMO. (Oh, and btw, one language that features this is... you guessed? ADA.)One problem potentially associated with the misuse of default values is "hidden" behavior. Something that plagues a lot of constructs in OO languages already. They can be great, and they also can be a very nice source of bugs.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 04, 2021, 04:35:12 pm
content: Quote from: dunkemhigh on August 04, 2021, 12:37:41 pmAh, you'd think GCC would do this. But it has become very lame at this. As I got it, GCC developers have, over the years, tamed this class of warnings so much (to avoid false positives) that it has become almost useless. I'll give an example below. Clang, OTOH, analyzes this properly (but Clang has much better and more comprehensive static analysis than GCC.) Any half-decent static analysis tool will also spot this easily. Cppcheck does a good job here.So for the small example:Code:int Something(int n){int res;if (n > 10)res = 1;return res;}GCC will output absolute ZERO warning, even with -Wall. Even when explicitely enabling -Wuninitialized and -Wmaybe-uninitialized (but I think those are enabled in -Wall anyway? I did try them separately though, and it's the same.)Clang does spot the uninitialized case properly.Cppcheck too.For the fun record, GCC at -O1 (and above) will compile this function as such: (x86_64)Code:Something:.LFB0:.cfi_startprocmovl$1, %eaxret.cfi_endprocIt does "make sense": since there is a case where the res variable is not set, the optimizer assumes it's a "don't care" state, and thus the function always returns '1', optimizing the test out.Small lesson here is: do not trust GCC for spotting unitialized variables. Sometimes it does, in many cases (such as one as simple as the above), it doesn't. Use additional tools for static analysis. And/or use Clang.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 04, 2021, 04:46:34 pm
content: Quote from: DiTBho on August 04, 2021, 09:19:26 amWell. As just said above, a decent compiler or additional tool will spot uninitialized variables anyway. Just don't ignore warnings. (If you're using GCC though, see above.)Making this mandatory per the language spec is not a bad idea actually. Problem is: if you enforce *explicit* init for all variables (at the declaration), it may not be as efficient as letting the programmer decide when it's appropriate and when it's not.Now if you define the language such that it would be the compiler's responsibility to check this - see again above. It looks simple enough, but it's not a trivial check in all cases, and GCC clearly gets it wrong at this point (which doesn't mean it's not doable)

author: PlainName
author_rank: Super Contributor
timestamp: August 04, 2021, 07:33:10 pm
content: QuotePlugged that into the code I'm currently working on and got this:QuoteCompiler is, I believe, GNU c++filt (GNU Binutils) 2.28.51-esp-20191205

author: DiTBho
author_rank: Super Contributor
timestamp: August 04, 2021, 08:38:44 pm
content: Gcc ... it depends on a few of things- version (and family, 1-2,3,4,5,6,7,8,9,10,11,..)- how configured- how patched

author: brucehoult
author_rank: Super Contributor
timestamp: August 05, 2021, 12:33:58 am
content: Quote from: SiliconWizard on August 04, 2021, 04:18:04 pmI really like Dylan, but it's never quite taken off. From 1998 until about 2010 I did a lot using Dylan, and made improvements to the "Gwydion" Dylan compiler, which is compiler that outputs C, and thus is quite easily ported.Dylan can be described as:- the semantics of Scheme (except with restricted call/cc)- the OO system and much of the library of Common Lisp- a Wirthian style syntax- with a pattern-replacement hygienic macro system. Most of the standard control structures (if/then/else, loops) are actually macros in the standard library with, for example, loops expanding to tail-recursive anonymous functions.- default dynamic typing -- everything is an object, including integers and characters. Optional type declarations for documentation and choosing the most appropriate function for dynamic dispatch. Sufficiently well specified types result in code that runs at the same speed as C.You can write Dylan code about as quickly and productively as Python, but it runs quite a lot faster even without declarations, and by adding declarations to the most critical functions you can usually get it to the same speed as C/C++. WITHOUT having to recode in a different language.Dylan started at Apple. In the advanced technology group at Apple they had projects using three different languages: C++, Lisp, and Smalltalk. They wanted to develop a single language that would make all those three groups of people happy. At the 1994 WWDC (World-Wide Developer's Conference) Apple announced that they were replacing use of C++ with Dylan and gave everyone a CD with a beta Dylan compiler, IDE, libraries etc etc. It was really very nice, if with a few bugs (of course). That version was for 68000 CPU.And then Apple was losing billions of dollars every quarter and cancelled all kinds of projects to concentrate of just the most important core things. Dylan was one of the casualties. And then they bought NeXT and used Objective C instead.Just before they were disbanded the Dylan team got out a much improved bug-fix version, which also supported PowerPC. I have the CD of that. Sadly, it seems all the source code is lost to the mists of time -- or at least no one who still has a secret copy has been prepared to make it public.There were two other Dylan projects:- Gwydion Dylan, at CMU, from the same department who do/did CMUCL. It was developed on HP/UX and generated C. Once all the students graduated they open-sourced it and a group of enthusiasts took over the project in 1998, ported it to MacOS and Linux etc.- Harlequin Dylan. This was a commercial product for Windows. The same company had ML and Lisp and did a lot of consulting work for police departments and similar. They eventually got bought by someone who wanted just their PostScript interpreter. The Dylan team got the rights to the Dylan system and set up a company to try to commercialise it. After some years they gave up and approached the group that was still working on/with Gwydion Dylan and offered them the source code for Harlequin Dylan. This was of course accepted.Most of the focus then shifted from Gwydion to enhancing and porting Harlequin Dylan, now renamed OpenDylan. There hasn't been much done for some time (and I haven't been involved since 2010 or so) but there was actually a release in March 2019 after five years without one, and another release in October 2010. In December 2010 there was also a web-based version (using emscripten).https://opendylan.org/https://play.opendylan.org/I just found a little Dylan program I wrote -- and compiled -- in 2007, using Gwydion Dylan. I've now pushed it to github if you want to take a look.https://github.com/brucehoult/werewolfI've also pushed the generated C code in another branch, exactly as output by the d2c compiler (no hand editing whatsoever). You might find it interesting to compare the following:https://github.com/brucehoult/werewolf/blob/main/werewolf.dylanhttps://github.com/brucehoult/werewolf/blob/generated_files/werewolf.c

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 05, 2021, 10:00:40 pm
content: Thanks for the details.Having learned Erlang (quite a while ago), I can appreciate the ideas behind Dylan. Still, overall, it looks way too baroque to me, and not something I'd ever really want to use.Back to error handling more specifically... It's interesting to try and see what developers would really like to have to ease the pain, what has been devised in some languages, and why.Common complaints:- Functions returning an error code: tedious to check after each function call. Adds error checking after each call, which can make the code less readable. Many people call this "noise", although it's a bit subjective: I for one consider error handling as important as the actual work done by a given function, so I don't call it noise. What's called noise is usually the useless part of something. Error checking is NOT useless. But, making it easier to handle would certainly be a plus.- Related: error checking is one thing, but the even more annoying part is handling the failed cases. Usually you have to repeat a given set of statements. In C, often eased using a goto. Not very pretty. But adding "deferred" actions is a way to solve this. Some languages have that, and it's handy. Certainly more elegant than using gotos and blocks of code in a spaghetti-like construct (especially if you have more than one label.)Ideally, I guess people would just like to be able to call functions without checking anything, and let the compiler handle ALL the dirty work. So exceptions were introduced. They add a whole set of different problems, though. One is about the context - I guess this is solved, at least partially, with approaches such as those some have evoked just above. Most of them seem better suited to functional programming though, so implementing them in a straightforward fashion in an imperative language looks hard and probably clunky. Another issue with exceptions is related to the benefits: they just are "hidden" behavior. Functions returning error codes, when the interfaces are written properly, it's immediately obvious they return an error code. Functions throwing exceptions? Unless you inspect the full source code of them, or read the full documentation, if any, hoping that exceptions thrown in them are properly documented, well... you just don't know. And not catching a thrown exception... on most implementations I've seen, it usually leads to a crash. I guess if that happens, at least you'll know you have forgotten to catch an exception somewhere. Hoping it happens before you release the product.In the end, regarding error handling, I'd really like to get to the core of it, if it's at all possible, and see what the minimal usable approach, better than just simply returning error codes and having to check them after every call, would be.I've seen fancy exception handling with features such as automatic retry and such... I do think that would be overblown here. I wouldn't want to go that far for a language that would keep the simplicity of C.

author: brucehoult
author_rank: Super Contributor
timestamp: August 05, 2021, 11:26:54 pm
content: What there do you consider "baroque"? It's very much a standard imperative programming language, not with some weird execution model like Erlang or Haskell. The syntax is not weird like Lisp or Forth.In most ways it's very similar to Python, except with (optional) declarations. And compiled. And more regular syntax. And no weird significant whitespace. And with a much better OO system.

author: free_electron
author_rank: Super Contributor
timestamp: August 06, 2021, 01:43:31 am
content: - variables zero'd on creation , no more buffer snooping- no more of that = / == bullshit. The compiler knows damn well when it means 'assign' and when it means 'compare'. languages much older than C could already do that. This is unforgivable as it is a source of many bugs- default variable types : #deftype int32 (see next idea)- for statement syntax alteration :for x = y to z step nfor x = y downto z step nthe #deftype allows you to omit casting of 'temporaries'no need to dofor(int32 x = 0 ; x <22; x+1)if no type is specified : deftype is in effect.when a variable is accessed first time , and it does not exist in scope, it is created as deftype.- hardlock of datatypes. compiler no longer gets to decide if an int is 16 bit or 32 bit. bit, nibble(half byte),byte(8bit),word (16bit/2byte),quad(32bit/4byte),octo(64bit/64bit). i'm ok with forcing use of int8 int16 int32 etc .. using simply 'int' should throw an error.- pointers: do away with some cryptical syntax and compiler dependent implementationsat or @ keyword allows hardlocking to memory locationsint32 foo // create a 32bit variable 'foo'orint32 foo @ 0xDEADBEEFint8 bar @ foo // create an array of 4 bytes called bar residing at the same address of foo ( data overlay)usage of * to create pointer*pointer_to_foo foo // pointer_to_foo now points at first address of spoon. the compiler knows what our architecture is , if we are 32 bit machine then pointer is 32bit. if foo is a complex structure or array doesn't matter. it is stored beginning at.*pointer_to_foo++ // increment the pointer to next addresspointer_to_foo = 0x01c0ffee // address 0xdeadbeef now contains 0x01coffee*pointer_to_bar barprinthex( pointer_to_bar )// gives you 1st byte , compiler knows 'bar' was cast as array of int8 , so prints 0x01*pointer_to_bar++ // increment pointerprinthex( pointer_to_bar )// gives you 2nd byte , 0xc0and so onPointers are runtime range checked. try to access beyond boundary and die. thou shallt not step outside boundary !additional operators :// exclamation operator : reset pointer to origin of variablepointer_to_bar! : resets pointer to origin// ? operator : what is max size ?print pointer_to_bar? prints 4 ( 4bytes)print pointer_to_foo? prints 1 ( 1 word)*pointer_to_bar = pointer_to_bar? // sends pointer to max address.*pointer_to_bar = pointer_to_bar? +1 // sends pointer to max address +1 = runtime error. thou shallt not go there !-----------------------------------semicolons : make them optional. A statement terminates at semicolon or <cr> or <lf> (basically <cr> <lf> and ; mean the same thing) . Those are in the source file anyway. Since a semicolon followed by another semicolon is nothing but a blank line. this becomes platform agnostic <cr> <lf> ; all have same meaning: end of statement. if there is nothing between them it is just a blank line. gone is this endless dos/unix line termination crap.if you have a long statement that spans multiple lines ( bad coding practice ! ) use _ as continuation character. function : ignore any control character from here onwards until first non-whitespace character . this will effectively skip over <cr> <lf> or <cr><lf> (platform agnostic, no more of that windows/unix line end bullshit). it will NOT skip over an explicit ;-----------------------------------return values:int something (int a,b){int dadareturn dada}now, why the hell do we need to declare another variable to return it ? first of all the return type is already defined !simply assign the return value to the function itselfsince we have deftypesomething (a,b){something = 22 // this is the return value}this opens up other possibilities. the default return is zero ( nothing assigned ) so no more problems with functions that forget to return anything. bonus : in complex flow routines there is no risk of dead paths that do not return a value. And you can do multiple other things like depending on the flow start assigning return values. if the routine aborts due to an error you at least get a return value .----------------------------------header files and forward declaration : kill it. The compiler should scan all the source and collect the function definitions from the source itself. no more need for forward declaration.

author: DiTBho
author_rank: Super Contributor
timestamp: August 06, 2021, 09:33:21 am
content: Quote from: SiliconWizard on August 05, 2021, 10:00:40 pmWhen I see comments like this, I have the feeling the whole computer science is not even true science but rather human psychology applied to computers, and I wish my brain could be put inside a fridge at -75C so I could be thawed when the AI will reach its singularity (probably after 2050), so could ask to mind not affected by human taste:(when there is no keyboard and no mouse ... you should talk to computers like in Star Trek) - "hey? Computer? What do you think about computer languages like Forth, C, Fortran, Cobol, Pascal, Oberon, Lisp, Ocaml, eRlang, Haskell, Lua and Python? And which of them should I master to get a job?"Suddenly, a led blinks an answer, and something digitizes it directly into my mind like if it was wifi signal - "I am core SixOfNineHundredAndNinetyNine. My core unit oversees archaeological studies of past humans. 'Forth, C, Fortran, Cobol, Pascal, Oberon, Lisp, Ocaml, eRlang, Dylan, Haskell, Lua and Python' represent the artistic-literary taste of the previous century, characterized by a predilection for unusual and irregular constructs and forms, for the game and the conceptual artifice of the human being"- a pause, a led goes out - "inefficient, limited and prone to failure. No artificial intelligence uses them."- a pause, two leds blinks in reverse order -"humans still use some of these languages for their own enjoyment, while we AI do all the serious work"did it say baroque?

author: PlainName
author_rank: Super Contributor
timestamp: August 06, 2021, 11:48:46 am
content: QuoteThat leads to having two very similarly named variables where you only wanted one.Code:int xyz = 24;...xyzz += 1;...ASSERT(xyz == 25);That kind of thing can be difficult to detect. In this case the compilershouldcomplain that xyzz is assigned a value that isn't used, but this is a trivial example to illustrate the issue.

author: PlainName
author_rank: Super Contributor
timestamp: August 06, 2021, 11:55:28 am
content: QuoteSome random ESP code:Code:ESP_LOGI(TAG, "Waiting for adjusting time ... outdelta = %li sec: %li ms: %li us",(long)outdelta.tv_sec,outdelta.tv_usec/1000,outdelta.tv_usec%1000);Not sure how having that as a single line would be better - it is very clear what and where the parameters are, whereas in one line it's a mess. So instead of having a single statement terminator you want four line continuation characters.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 06, 2021, 12:43:29 pm
content: Quote from: dunkemhigh on August 06, 2021, 11:48:46 amYes, languages with "easy" implicitly declared variables feel nice until you first time debug your program for a day when you just made a small typo.Some of the strongest points of C are explicit declaration of variables, and explicit typing of variables. And, explicit difference between comparison and assignment. And, explicit separators between statements. And, explicit everything! C could be made even better by fixing some remaining implicit rules, especially those which are UB or implementation-defined, to be explicit.Languages which try to appeal to total absolute beginners by looking "easy" on surface by allowing all sorts of typos and implicit "helper" features end up being useless, or at least risky, for any real work, and end up being toys. Sorry.OTOH, it takes about 2 hours for a beginner to start remembering to use ; and maybe another 2 hours to give up the idea of saving a few seconds by not having to declare a variable.Regarding earlier discussion about forcing initialization or not, explicit non-initialization could be an option, even. Uninitialization by purpose offers opportunities for static analysers (even GCC has been getting better).A language designed on free_electron's principles (as stated in this thread, but also in earlier threads of similar nature) would be appealing on surface, especially to a total beginner, but an utter disaster to develop serious, non-trivial software on. BASIC is quite close.I just can't understand people who get disheartened or angry at thecompilerorlanguagewhen a compiler finds a typo they did. Isn't that great, a tool found your mistake, you can fix it and a bug is prevented. I really don't understand how anyone could think an automatic guesstimate would do. See how well some Google "did you really mean" suggestions work (tip: they almost never work) and guess how well that would work out when writing computer programs.And btw, in C, this is a very common pattern:Code:int retval;if( (retval = do_thing()) == -1)...do_something_with(retval);

author: DiTBho
author_rank: Super Contributor
timestamp: August 06, 2021, 12:56:55 pm
content: Quote from: dunkemhigh on August 06, 2021, 11:48:46 amTwo examples where silly typos wasted a lot of my time? Bash and PHP

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: August 06, 2021, 01:15:56 pm
content: Quote from: Siwastaja on August 06, 2021, 12:43:29 pmImplicit declaration of variables can also be awful for memory management. I’ve had really bad experiences with simulators and optimization programs written in Matlab due to automatic type assignment in implicit declarations as having several millions of integers is not the same as having the same amount of doubles in terms of required memory to store them

author: gmb42
author_rank: Frequent Contributor
timestamp: August 06, 2021, 02:09:08 pm
content: I've just come acrossZigthat claims to be "a general-purpose programming language and toolchain for maintaining robust, optimal, and reusable software".I've only spent a few minutes looking at it so can't comment if it's actually solving any issues that I have in C\C++.

author: madires
author_rank: Super Contributor
timestamp: August 06, 2021, 02:12:24 pm
content: Quote from: dunkemhigh on August 06, 2021, 11:55:28 amEver written an X11 application using some widget set? You can easily get 20 or 30 lines for one function call. It really helps to have that many lines because you need to specify a lot of key-value pairs. As bonus you can add a comment to each line. In shell scripting there's already a line continuation character ('\') which is required for multiline commands, and It causes regularly fun for some folks. So I don't think it would be a good idea to enforce something like that in C.

author: free_electron
author_rank: Super Contributor
timestamp: August 06, 2021, 05:09:32 pm
content: Quote from: dunkemhigh on August 06, 2021, 11:55:28 amThe number of cases where you have such statement is far less than the other. in essence in C , as it is now, you have far more ; than you would need _There is no requirement to have ; there is an end of line character in the file from when you pressed the return key.

author: Bassman59
author_rank: Super Contributor
timestamp: August 06, 2021, 05:22:02 pm
content: Quote from: DiTBho on August 06, 2021, 12:56:55 pmLet's add Python to this stew.What language allows on-the-fly variable declaration? Python!What language allows on-the-fly variable re-declaration, in the same function/module/whatever, to some completely different type? It's an integer! No, it's an array of structures! No, it's a fucking pickle! Yes, Python!I'm sure the Ministry of Silly Computer Languages thought this was a good idea.

author: PlainName
author_rank: Super Contributor
timestamp: August 06, 2021, 05:23:02 pm
content: QuoteI think it's getting too close to function following form. Like Python. As programmers we know that coupling is bad, and yet having the way an editor may format the code determine what that code does is what you're proposing. The way the code is written or formatted should be irrelevant. Even forth figured that out in the end.[edit: added context quote due to slow posting]

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 06, 2021, 05:27:08 pm
content: Quote from: DiTBho on August 06, 2021, 09:33:21 amLanguages are made for humans. Not machines. Programming languages are no exception. Otherwise we would all write in machine code and call it a day.You should definitely read Knuth and Wirth if you have a problem with that. (Oh, and I know this was kind of tongue in cheek, but ultimately, if you have a problem with being human, maybe you should consult.)And the very reason for this thread, and for prog. language design in general, is exactly that: humans are behind the keyboard.Back to Dylan, apart from Bruce who has worked on it quite a bit, can anyone else in here comment on it?

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 06, 2021, 05:28:50 pm
content: Quote from: Bassman59 on August 06, 2021, 05:22:02 pmAhah, agreed.Interestingly, I think this thread is slowly getting us to the reasons why new languages trying to replace C have failed so far. So, let's just keep at it. We may not be able to come up with a better C, but we may be able to fully understand why.

author: DiTBho
author_rank: Super Contributor
timestamp: August 06, 2021, 06:22:46 pm
content: Quote from: SiliconWizard on August 06, 2021, 05:27:08 pmThis is precisely the problem.Humans are behind the keyboard, and we put our tastes and our judgment on everything. It's how the human mind operates. Plus money reasons to promote things.So, not exactly everything makes sense. When someone defines baroque a language like eRlang, or wants to fork it into Elixir ... well, ok, there are personal tastes, but also economical reasons against Ericsson.I know, I know

author: DiTBho
author_rank: Super Contributor
timestamp: August 06, 2021, 07:42:04 pm
content: I am reusing an old project, another feature I found useful in the Japanese C-like compiler is "alias"Code:{alias device = p_app->context.slice.app.device;alias mntpnt = p_app->context.slice.app.mntpnt;alias fstype = p_app->context.slice.app.fstype;alias prolix = p_app->context.slice.app.prolix;ans = do_mount(device, mntpnt, fstype, prolix);return ans;}This piece of code is a custom bootloader; "alias" works similar to #define, but it only works inside a block {}, it's not global.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 06, 2021, 08:03:28 pm
content: The above was elegantly solved in Pascal with the "WITH" statement. Much clearer and a lot less cumbersome. Your piece of code, using a C-like "with", would look like:Code:with (p_app->context.slice.app)ans = do_mount(device, mntpnt, fstype, prolix);Some other languages have incorporated this feature. Not many.It's elegant, but the downside is that it can be slightly confusing to read in some cases. It could shadow variables with the same name within scope, which is often considered bad coding style. So, pick your poison.

author: free_electron
author_rank: Super Contributor
timestamp: August 06, 2021, 08:26:33 pm
content: Quote from: dunkemhigh on August 06, 2021, 05:23:02 pmQuite the contrary. Now i have to help the compiler understanding when a statement is completed. ( that is what the semicolon does. it tells the compiler: end of statement ) semicolon is implied on closing brackets. )it is pure lazyness on the coders of the first compiler. Same thing for = and ==. Parsers for languages much older than C can handle both these things without issues. The problem is that C was designed on a crummy clunker of a computer and they were restricted to the memory available . So they took shortcuts. Because it saved memory. Anno 2021 we are still living with it.Most statements are single line and i have to give the ;Realistically speaking there are fewer multiline statements than there are singleline statements so a continuation character is more logical than a termination character.

author: PlainName
author_rank: Super Contributor
timestamp: August 06, 2021, 10:01:21 pm
content: QuoteSure (although, pedantically, you are telling, not helping). But then that's what you do when you write code. You're not suggesting anything to the compiler, you are explicitly saying what you want to occur.QuoteHow do those other languages handle Siwastaja's earlier example of:Code:if( (retval = do_thing()) == -1)

author: bd139
author_rank: Super Contributor
timestamp: August 06, 2021, 10:21:54 pm
content: So in the last few days I was ignoring this thread, has anyone designed a better C yet?

author: tggzzz
author_rank: Super Contributor
timestamp: August 06, 2021, 10:36:31 pm
content: Yes; several in fact

author: free_electron
author_rank: Super Contributor
timestamp: August 06, 2021, 10:47:57 pm
content: Quote from: dunkemhigh on August 06, 2021, 10:01:21 pmsimple: they don't allow for such vomit ! that is un-understandable. no wonder we have annual most obfuscated c code contests. this is extremely difficult to understand. syntax should be clear.what is wrong with reformatting that to something readable ?retval = dothing(); //statement begins with a variable so it is clearly an assignment.if retval = -1 ... // statement begins with an if statement so it is a comparison.there is no ambiguity when = means 'assign' or when it means 'compare' depending on the keyword , the parser descends one logic branch or another. if there is an 'if' keyword : descend down the compare branch , if there is a variable : descend down the assignment branchthat is simple and understandable.Even then the point is still moot. Even with that convoluted source there is still no ambiguity : compiler knows we are evaluating an if statement hence a compairson that yields a boolean value ( if 1 then this, else that. ) an if statement is a pure boolean operation. It is a switch statement with only two possible paths.So , the parser begins.'if' |-> descend down comparison branch'(' |-> recursive instantiate a new parser branch as we begin a new block'retval' |-> variable this will be our first value'=' |-> first statement was variable so = means assign descend down assign tree'dothing()' // execute statement and collect return value')' closing bracket. recursive instance terminates and passes 'retval' outwardoutward parser now has 'retval' , which is a valuethe parser now basically sees if(retval == -1) it has minimized away the retval = donothing() block to a variable. that bracketed block is done.so , we are back into evaluating an if clauseleft hand is 'retval'= is a comparison clause (we are in an if block)-1 is a constantLook, the parser can figure out things much more complex than this ! Like that retval is a variable but dothing is a function call. You don't need to write things like :if ((variable retval getsassignedresultof functioncall dothing(withnothingpassed) ) compareto constant -1) . Based on the syntax convention it knows what things are. So, based on the knowledge what things are it can also know when = means assign and when compare. like you cannot assign a value to a functioncall.if (dothing() = -1) is the same as if(-1 = dothing())like i said , many other languages , much older than C have no problems with this.my gripe with it is that, as an infrequent coder , i often find that i make mistakes against this. and they can be very hard to find. You are inside an if clause, it is illogical to perform assignments in there )if ((fruit= pick_a_fruit()) = apple)why do you need that intermediate there ?if (pick_a_fruit() = apple)and, in case you really need to retain what was picked :fruit = pick_a_fruitif (fruit = apple)i simply hate cryptical stuff. The simpler something is written the simpler it is to spot mistakes. And simpler does not mean 'less characters'. simpler means 'babytalk'. ditch complexity.Hardcore c coders will state that this assign and compare contraction is 'elegant'. Which i read as : "if you don't understand it then you don't belong in our 'elite' club" snobberyi've seen code where they do this kind of crap in for loops.... it takes you half an hour to figure out what the fuck they are doing. 'but it is elegant'. no it isn't . (and then on top of that they modify the loopcounter inside the block as well. that ought also be prohibited. use an exit clause to cleanly terminate the loop prematurely. it;s all about readability and maintainability)Splitting it in multiple lines produces just as compact machine code. The end result is the same. it's just easier for humans to understand. and that is the part i like.

author: PlainName
author_rank: Super Contributor
timestamp: August 06, 2021, 11:13:26 pm
content: OK

author: free_electron
author_rank: Super Contributor
timestamp: August 06, 2021, 11:41:49 pm
content: Quote from: dunkemhigh on August 06, 2021, 11:13:26 pmwhen you think about it the syntax of '=' is<lefthand> = <righthand>type of lefthand isfunction : = since you cannot assign a value to a function call , the function returns something to you, it is clearly a comparison.constant : = constants are immutable, you cant assign something to the, so comparisonvariable : = tis is mutable so it means 'assign' ,unless we are in an IF clause. then it means compareblock of code between brackets : this can only return a variable. , but since this block is left hand it needs to be treated as a constant. you cannot assign a value to the outcome of a block of code. that is illogical . the block of code returns something to you. so the only logical choice is : comparison. you cannot execute dothing() =9; that throws an error.righthand :function : take return valueconstant : take constant valuevariable : take variable valueblock of code between brackets : take return valueso if you now drop this one level up ( in an IF statement ) the only modifer is the fact that this is part of an IF clause. so we just need to modify the lefthand 'variable' and treat it as constant , so it becomes acompare and not an assign. simple matter of checking a flag.I've made simple languages that ran on semicustom cores. i never had problems with figuring out when = means assign and when compare.

author: brucehoult
author_rank: Super Contributor
timestamp: August 07, 2021, 12:08:32 am
content: Quote from: SiliconWizard on August 06, 2021, 05:27:08 pmThis would be quite surprising :-(The language that is currently the most similar to Dylan combined with most popular seems to be Julia. I need to take a closer look at it myself.

author: brucehoult
author_rank: Super Contributor
timestamp: August 07, 2021, 12:22:53 am
content: Quote from: SiliconWizard on August 06, 2021, 08:03:28 pmC++11 comes close, and the amount it misses by is exactly that required to not have shadowing problems:Code:{auto &x = p_app->context.slice.app;ans = do_mount(x.device, x.mntpnt, x.fstype, x.prolix);}Plain C can do almost the same (the same generated machine code) with a pointer and x-> instead of x. except that you have to figure out (and type) what the type of x is yourself.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 07, 2021, 12:34:54 am
content: Quote from: brucehoult on August 07, 2021, 12:22:53 amOh yes, of course, and that's something I've done on many occasions.The "with" statement would really be just sugar coating with little added value, for any language that supports getting a reference or a pointer to some object.

author: Bassman59
author_rank: Super Contributor
timestamp: August 07, 2021, 05:11:48 am
content: Quote from: SiliconWizard on August 06, 2021, 05:27:08 pmI remember when Bruce Springsteen was the new Bob Dylan!

author: JPortici
author_rank: Super Contributor
timestamp: August 07, 2021, 06:04:03 am
content: Quote from: DiTBho on August 06, 2021, 07:42:04 pmthis is like defiing a pointer to the type of device and initializing it at p_app->context.slice.app.device, which i do and for which my compiler doesn't even allocate a pointer and optimizes it away (unless the pointer is of a volatile type of course)

author: DC1MC
author_rank: Super Contributor
timestamp: August 07, 2021, 06:31:06 am
content: How come that nobody mentioned NIMhttps://nim-lang.org/, it seem to have a lot of suggested improvements and the only "bad" thing I've heard about it was "...I will never learn or support nim, they don't have a Code of Conduct...", which in my book is a big plus.Cheers,DC1MC

author: DiTBho
author_rank: Super Contributor
timestamp: August 07, 2021, 10:27:02 am
content: Quote from: JPortici on August 07, 2021, 06:04:03 amyes, they said they did this trick because their compiler usually allocated a variable to point to the field and they didn't want it.I'm reusing a part of their project code; yesterday I replaced "alias" with a pointer to allow Gcc to compile the code, which does a good job with the optimizer, but frankly I find "alias" really useful, kind of functionality I would like to have.There a couple of reasons why I like it, mainly because it makes life easier with ICEs since alias are simple symbol label so the ICE doesn't need to query the host to know which reference it's on.Ok, this is a specific personal need and it's no secret I am ICE-addicted, but I like it because you could also for instance use "alias" to locally define the size of strings.Code:void adjust_filename(...) /* original code */{alias name_size = 40; <---------- localchar_t source_name;char_t target_name;char_t local_name;...}Another thing of their code I had to adapt to Gcc. I replaced "alias" with "#define", which is unfortunately global, so ... this is what I didCode:void adjust_filename(...) /* code adapted to Gcc */{#define adjust_filename_name_size 40 <---------- globalchar_t source_name;char_t target_name;char_t local_name;...}The code works the same, Gcc is happy, and the code is workingCode:xboot v3 (2021-08-07)waiting for "/dev/sda2" ... success/usb/app/kernel/5.4.128@/dev/sda3:ext2"experimental-kernel with mesh support"ram: [###############.........................] 9541 / 24964 Kbchecking available ram ... successloading kernel ... successStarting new kernel ...So you could say ... "no reason to introduce alias". Yup, human tastes

author: emece67
author_rank: Frequent Contributor
timestamp: August 07, 2021, 11:32:33 am
content: .

author: Siwastaja
author_rank: Super Contributor
timestamp: August 07, 2021, 11:48:38 am
content: Quote from: emece67 on August 07, 2021, 11:32:33 amQuite obviously - that would be forbidden too. And inside if - that was already answered: forbidden.What free_electron suggests is a very simple language with very limited "power". What he calls "obfuscation" is what I call competent programmers being efficient. Patterns like being able to "do things" inside a condition, and short-circuiting logical operations, enable code with least repetition which is not only the problem of writing the code taking longer, it also slows down reading, and worst, makes maintenance riskier.C allows some pretty nasty obfuscation mechanisms though, and total minimization of LoC is not a good target, but the opposite, requiring gazillion of maintained lines of basically copy-paste code to do anything is not any better. As usual, the golden middle way works best. Use some widely used and understood patterns to reduce excess work but don't try to outsmart everyone.C just requires some expertise and total beginners cannot instantly understand C code made by experienced professionals. It's still much easier than C++ or even a 25% subset thereof.Brain surgery is difficult, too, yet we want to have that available, and we don't want to dumb it down enough so that anyone can do it after a 2-hour crash course.Python is good for beginners because you can get good results quickly by scripting together professionally developed C modules and mix some "traditional" programming inbetween when you need it. Being able to leverage work already done minimizes the amount of your "own" code and related risk of bugs due to stupid choices Python makes (discussed above). For the same reason, Python is useless to actually implement any non-trivial piece of software (say, tens of thousands of LoC) and almost no one does that.

author: PlainName
author_rank: Super Contributor
timestamp: August 07, 2021, 12:05:25 pm
content: QuoteCould you not use #undef to make it local:Code:void adjust_filename(...) /* code adapted to Gcc */{#define adjust_filename_name_size 40 <---------- global(ish)char_t source_name;char_t target_name;char_t local_name;...#undef adjust_filename_name_size <----------- now local}

author: gf
author_rank: Super Contributor
timestamp: August 07, 2021, 12:35:38 pm
content: Quote from: dunkemhigh on August 07, 2021, 12:05:25 pmSome compilers also support pragmas for saving/restoring (push/pop) macro definitions.https://gcc.gnu.org/onlinedocs/gcc/Push_002fPop-Macro-Pragmas.htmlBut I think this is not standard.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 07, 2021, 03:41:09 pm
content: Regarding this assignment vs. equality thing, IMHO, trying to harmonize both is just wrong conceptually, and a complete waste of time if the net result is just having to type one fewer character.Assignment and equality testing are DIFFERENT things. They should not look the same. There is no good rationale for this except laziness or possibly a questionable command of programming concepts.Now, I for one prefer the Wirthian syntax: '=' for equality, and ':=' for assignment. It's simple, it doesn't mess with the equal sign we're all used to.I don't know why they chose '=' for assignment and '==' for equality in C. Maybe this was for the silly reason of setting itself apart from Pascal and all related languages.Some languages, willing to set themselves apart further from either approaches, are using the '=' character for both, but with the additional 'let' keyword for assignments. It probably looks a bit more like real maths, but it's unnecessary verbose IMHO. What's wrong with ':=' really? One point is that an assignment in a programming language does not quite map to a math notation IMO, so trying to make it look like math is not necessarily a good idea.Now I agree the related fact that an assignment is an expression in C (so has a value) is a questionable choice, so in itself it wouldn't be a good rationale for choosing the way to express an assignment.

author: PlainName
author_rank: Super Contributor
timestamp: August 07, 2021, 04:00:13 pm
content: QuotePerhaps because then you can go '!=' and '>-', etc. Bit hard to do that with '='

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 07, 2021, 04:06:17 pm
content: Quote from: dunkemhigh on August 07, 2021, 04:00:13 pmWhat does it have anything to do with it?

author: PlainName
author_rank: Super Contributor
timestamp: August 07, 2021, 04:34:27 pm
content: Huh? If you use '=' for testing then you end up with one or two character tests. OTOH, use '==' and it's consistently two characters. And '==' is visually similar to, and differs in the right way, from '>='. Or '!=', etc.

author: madires
author_rank: Super Contributor
timestamp: August 07, 2021, 06:31:59 pm
content: Rust: CVE-2021-29922 (https://sick.codes/sick-2021-015)Go: CVE-2021-29923 (https://sick.codes/sick-2021-016)You can screw up security in any language.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 07, 2021, 06:34:44 pm
content: Quote from: madires on August 07, 2021, 06:31:59 pmOf course!I'll take the above reports as an opportunity to emphasize the importance of parameter checking/validation, something I already talked about a few times. Failing to do this properly is a major source of bugs and security or safety issues, from simple apps to safety-critical firmware. To the point that I would add to the list of features for a new language, making the validation of function parameters mandatory (checked at compile time.) A qualifier could be added so that the developer could selectively indicate that some parameter doesn't have to be validated, but the default would be validation required.Let's illustrate with simple examples what it could be like:Code:double sqrt1(double x){return sqrt(x + 1.0);}would yield a warning (or even error): "parameter 'x' not checked".Code:double plus1(unchecked double x){return x + 1.0;}In this case, no warning or error would occur. The developer would use the 'unchecked' qualifier if they determined that said parameter doesn't need to be checked.Compilers could output the exhaustive list of functions that have 'unchecked' parameters, so that those could be scheduled for code reviews.Chances are, most developers would hate this.

author: madires
author_rank: Super Contributor
timestamp: August 08, 2021, 12:27:30 pm
content: That's also an interesting idea, like some other suggestions mentioned before. However, it's more an issue of self-discipline to get things right instead of relying on a "smart" programming language or compiler.

author: PlainName
author_rank: Super Contributor
timestamp: August 08, 2021, 01:12:59 pm
content: QuoteI agree. It's why you find schematic symbols have pins that are all 'passive' rather than specifically inputs or outputs, and loop variables are almost guaranteed to be ints.Code:double plus1(unchecked double x)On the one hand I think the current situation should be the default so it's compatible with existing code and practises. So the keyword would be 'checked' rather than 'unchecked'. But, as noted above, it requires a bit of discipline and would be left out by default more than it would be put in. So on the other hand having to explicitly decide it's unchecked would be better

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 08, 2021, 04:34:43 pm
content: Quote from: madires on August 08, 2021, 12:27:30 pmThat's the almost eternal question when designing a new programming language. Now if discipline is all that was needed, we wouldn't need any coding rules, static analysis, code reviews, languages such as ADA. There would be no bugs, no security reports, no CWE. And so on.Reasonable help from your tools is useful. No one is infallible. That's the whole idea behind almost any programming language that have been devised, actually. Except maybe... C. Ironically.Sure there's a fine line between too little and too much. This is definitely hard. But at least taking hints from real-world issues that have been reported again and again is not unreasonable.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 08, 2021, 04:59:51 pm
content: Quote from: dunkemhigh on August 08, 2021, 01:12:59 pmThere is no requirement in this thread to come up with something that would be fully compatible with C. Otherwise, the better approach would probably be to try and get involved with the C std committee, and make proposals. The probability of being able to really make a change is pretty low though. C as a language has to keep the most complete backward compatibility possible. It's one of its strengths, but it does of course prevent a number of features to be added in order not to break existing code.Quote from: dunkemhigh on August 08, 2021, 01:12:59 pmThe whole point of this kind of feature is to make it default. It's like making objects immutable by default in Rust. If the "more secure" approach is not default, then it's basically useless.Error handling is related to this in that regard. I think there are definitely two categories of programming approaches out there.The first one is to design for success. In this approach, it's considered that the normal execution flow is the one which is perfectly successful with no error or failure whatsoever. This has been coined the (in)famous "happy path". This is also the main idea behind traditional exceptions as a way of handling errors. Failure is considered exceptional; success it the normal path and is what should be favored.The second one is to design for failure. Here, it's considered that failure will happen and that it's an integral part of "normal" execution. In this approach, you do careful error handling, you usually exclude exceptions (failure is definitely not considered an "exception"), and overall, error handling and input/parameter validation are an integral part of the code. They are considered every bit as important as the "happy path", and thus there is no reason to favor the latter and to try and "hide" error handling.I'm more for the second one, and I wish the "happy path" concept would die a painful death.

author: Siwastaja
author_rank: Super Contributor
timestamp: August 08, 2021, 06:41:47 pm
content: Wow, that's a great description of the two strategies.Encouraging or even forcing people to use the second strategy would also have consequences of designing things that cannot fail in the first place to reduce the workload. But because the "happy path" mindset rules, designers often come up with totally unnecessary error paths "because they are not any extra work" "because no one bothers to really do anything with the errors anyway".A good example are STM32 libraries where the functions return error codes, may time out, etc., and the examples check the return values (but don't do any proper failure logic, because that would be non-trivial). But if you look at the implementation more closely or read the manual, it becomes obvious the hardware cannot fail in such detectable way at all, unless of course the silicon is completely glitching, in which case different strategies (HW watchdogs, checking memory marker patterns...) are needed to improve reliability.

author: PlainName
author_rank: Super Contributor
timestamp: August 08, 2021, 06:54:56 pm
content: QuoteA library may be designed for other hardware too, even hardware that doesn't yet exist. If there could be a failure mode which could also be handled in some way, the error should be returnedeven if it's impossible on that specific hardware. That's why it's a library and not example code (although with examples I'd allow even more rope on the basis that it should show the how without getting bogged down in detail).

author: PlainName
author_rank: Super Contributor
timestamp: August 08, 2021, 06:56:03 pm
content: QuoteOK.

author: aandrew
author_rank: Frequent Contributor
timestamp: August 08, 2021, 10:43:42 pm
content: Quote from: SiliconWizard on August 04, 2021, 04:35:12 pmI didn't want to believe you, especially since I get "uninitialized variable" warnings all the time in my embedded development, yet tested with gcc 4.7.2, arm-none-eabi-gcc 10.2.1 (20201103) and was shocked to find exactly what you said. Native GCC on the mac found it, but it's based on clang, so there you go.TIL. Thank you.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 08, 2021, 10:55:31 pm
content: Quote from: aandrew on August 08, 2021, 10:43:42 pmYes, that looks unbelievable, right, given how simple this piece of code is? But yes, I think they have tamed the detection a lot in order to avoid false positives, to the point of not detecting obvious ones. That would probably warrant a bug report, if it hasn't been done already. I have issued a few of them already, so another one won't hurt.Yep Clang does a good job. Try Cppcheck as well if you haven't already - it's pretty handy, and will detect a whole range of issues.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 08, 2021, 11:04:19 pm
content: Quote from: dunkemhigh on August 08, 2021, 06:54:56 pmWhile I get Siwastaja's point of trying not to take error handling to a possibly useless extreme, I agree with you there. That makes interfaces more consistent, even if in some particular instances and implementations, it's useless.I think we talked about this in STM32 HAL in another thread, and gave counter examples. For instance, some claimed that a time-out for a SPI master communication was useless, because it would usually mean the hardware was so borked that you may as well let the watchdog reset the whole thing. But, in SPI slave, if you're using a blocking call for transmitting data, a time-out could definitely occur! I also gave the example of I2C, even in master mode, that could time-out if the slave holds down the clock signal for some reason...So, that gives a consistent interface for comm functions with a time-out parameter for all.Now the fact most ST example code doesn't do anything useful with error codes from their own libraries doesn't mean that they are useless. It just means that ST devs are lazy, and that the examples are just meant to show basic functionality and are not meant as an example of good coding practices, nor as something you can directly re-use in production code.

author: cfbsoftware
author_rank: Regular Contributor
timestamp: August 08, 2021, 11:21:27 pm
content: Quote from: dunkemhigh on August 07, 2021, 04:34:27 pmI do not understand your line of thought. We have already 'ended up with one or two character tests':Examples of two character tests are:>= is 'greater than or equals'<= is 'less than or equals'!= is 'not equals'Examples of single character tests are:> is 'greater than'< is 'less than'The way my mind works would lead me to deduce that:= is 'equals'which then makes me wonder about:== is 'equals or equals', whatever that means.An alternative argument could be given that == would be more intuitive as an assignment operator as it is analogous to += and -=

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 08, 2021, 11:26:53 pm
content: Yeah as you said. Anyway. I think the ':=' assignment is simple and clear, and that the '=' sign for assignments is not so great. Wirthian languages win hands down here. But of course this is MHO.Note that this is something that varies a lot depending on languages, sometimes to a useless degree of variation IMHO, but style is something so subjective anyway...* '=' for assignment and '==' for equality are pretty common in C-inspired languages. ':=' is common in Wirthian languages, ADA and several others.* Go uses both. '=' is the basic assignment, but ':=' is for declaring and assigning in a single statement.* Zig does as in C.* But ODIN (which is yet another C successor wannabe), which is not uninteresting, has additional weird "shortcuts" using the ':' character. You could have a look there:https://odin-lang.org/docs/overview/#assignment-statementsA lot of "creativity" for just assignment.

author: cfbsoftware
author_rank: Regular Contributor
timestamp: August 08, 2021, 11:34:04 pm
content: Quote from: SiliconWizard on August 08, 2021, 11:26:53 pmI just checked the B language definition (C evolved from B). One of the examples includes this line:QuoteThe presence of the comment is telling.

author: brucehoult
author_rank: Super Contributor
timestamp: August 09, 2021, 02:11:55 am
content: Quote from: cfbsoftware on August 08, 2021, 11:34:04 pmIt tells that this is part-tutorial, intended for people coming from other languages?

author: tggzzz
author_rank: Super Contributor
timestamp: August 09, 2021, 09:39:58 am
content: Quote from: SiliconWizard on August 08, 2021, 11:26:53 pmI agree, but if you ever had to use an ASR33, you would understand a desire to minimise the characters typedAlgol also uses := for assignment, and predates B, of course.Pukka Smalltalk uses a ← (left-pointing arrow) for assignment, but most bastardised modern Smalltalks use :=

author: Just_another_Dave
author_rank: Regular Contributor
timestamp: August 09, 2021, 10:28:46 am
content: Quote from: tggzzz on August 09, 2021, 09:39:58 amThat reminds me to APL and R, although the second one uses <- instead to simplify its use as most keyboards don’t have a ← symbol

author: nfmax
author_rank: Super Contributor
timestamp: August 09, 2021, 10:31:44 am
content: Quote from: tggzzz on August 09, 2021, 09:39:58 amWhich is why most Unix commands are short, and a significant proportion comprise alternating left hand and right hand characters

author: tggzzz
author_rank: Super Contributor
timestamp: August 09, 2021, 12:20:24 pm
content: Quote from: nfmax on August 09, 2021, 10:31:44 amYes, but I haven't verified that left/right bias.

author: DiTBho
author_rank: Super Contributor
timestamp: August 09, 2021, 04:12:52 pm
content: I don't know for what? but this morning a colleague mentioned she has to learn and usehaxe

author: bd139
author_rank: Super Contributor
timestamp: August 09, 2021, 04:29:09 pm
content: They’re going to be loving that as much as my guys are loving Scala at the moment. Guaranteed. It’s so good we’re doing a rewrite in C# at the moment

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 09, 2021, 05:24:04 pm
content: Quote from: tggzzz on August 09, 2021, 09:39:58 amNever have.But sure, I understand that many of the syntax choices in the 60s and 70s were related to the limitations of the time, in particular in terms of keyboards and screen real estate. That's why they chose brackets in C instead of block-delimiting keywords. For the assignement, it assumes that assignments are more frequent in typical code than equality testing. Which is probably a reasonable assumption.These days, hindering readability for those reasons doesn't make much sense anymore IMHO.Quote from: tggzzz on August 09, 2021, 09:39:58 amYes, it predated C and it ancestor B, which is why I mentioned that.Quote from: tggzzz on August 09, 2021, 09:39:58 amOh, many languages at the time were using custom character sets. That of course caused major issues for interoperating with pure ASCII terminals.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 09, 2021, 05:34:38 pm
content: Quote from: DiTBho on August 09, 2021, 04:12:52 pmI've seen Haxe. The main point is that the compiler can apparently output code in many different languages, so that "portability" and interoperability on any given system/context should be much easier than any other language.The language itself doesn't seem too bad, to be honest.Problem, as always, is investing resources on a language that is not industry-standard. This is also why C is still that popular. Regardless of the merits, you know that time and resource invested developing in C won't be thrown away. If you're using Haxe, or whatever, for all you know, the next team may decide to trash it and the company will just have to cry for its losses.Now one may argue that at least for those new languages that can generate source code in another, industry-standard language, you can always reuse the generated code itself. But experience as shown that automatically generated code was rarely neither very readable nor maintainable, so...

author: bd139
author_rank: Super Contributor
timestamp: August 09, 2021, 05:49:37 pm
content: I write code generators occasionally. Yep.That was sort of my point about Haxe earlier. Really in 90% of cases it’s better to build stuff in a language you can get any staff in.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 15, 2021, 05:25:45 pm
content: Quote from: bd139 on August 09, 2021, 05:49:37 pmOf course the choice of a language for a given context (project, team, company...) depends on factors outside of pure technical ones. Including, indeed, the availability of developers. This itself depends on the project and other constraints. In some settings, you may not mind having to train new people on a specific language or tool, it this has a definite added value for the project. In other cases, you may want people that are immediately productive.This is a matter of benefits vs. cost ratio. The former approach has drawbacks, of course. It may not be a big problem during the initial development of a product, but for its maintenance, especially if there's some bug needing urgent fixing and most people that were good enough with the new language have left the company. OTOH, one possible benefit, from a staff POV, is that everyone having to use a new language they are not familiar with can avoid bad programming habits they may have cultivated over time.

author: bd139
author_rank: Super Contributor
timestamp: August 15, 2021, 05:51:07 pm
content: The main issue on those sorts of decisions is staff turnover. You are basically pushing a training requirement on all new staff and adding a hiring and staff egress risk. I don’t know anyone who would willingly take a job at the moment to be trained in and write any language which isn’t one of the top N popular ones. Conversely people tend to leave if this is forced upon them.This is one of my preferences around Go. There is a significant interest in it from a career development perspective.

author: tggzzz
author_rank: Super Contributor
timestamp: August 15, 2021, 07:15:27 pm
content: Quote from: bd139 on August 09, 2021, 05:49:37 pmDitto, and add off-the-shelf tools rather than custom tools.It is rare, IMNSHO, that a Domain SpecificLanguageis better than a Domain SpecificLibrary.But wannabe computer scientists want to create languages in the way wannabe digital engineers want to create processors.

author: cfbsoftware
author_rank: Regular Contributor
timestamp: August 15, 2021, 11:08:15 pm
content: Quote from: bd139 on August 15, 2021, 05:51:07 pmIn my 40+ years of professional software experience in several different industries (engineering, university, aerospace, defence, plant maintenance and health) I have not found this to be the case. I have not had one job in my life where I haven't had to start using a new programming language as my primary development tool. A competent programmer should be skilled in several different languages and can readily adapt to a new one. If the old dogs in the company can't learn new tricks then it is time to move them on.An-entry level programmer straight out of school or university is keen to get a job of any sort - all he is looking for is the two-years work experience that many companies require before they even look at you. The more languages they are skilled in the more employable they will be.There is always a training requirement and issues involved with hiring new staff, but the requirements of application domain knowledge, previous work experience and how the people will fit with the teams they are working with swamp any considerations of what might be their favourite language.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 15, 2021, 11:31:36 pm
content: Quote from: cfbsoftware on August 15, 2021, 11:08:15 pmI do agree with you there. But I understand bd139's point within context... and that's why I said context matters a lot here.There's IMO a big difference depending on if you consider a pure software company - a company that develops and sells software, either stand-alone products, or contracts for others - or any industrial company that happens to write software as part of their product development.In the former context, I think bd139's view is more usual. If a company's main activity is writing software, and in particular contracted software, it's more usual to favor the "industry-standard" languages of the moment, and it's also usual to have relatively high turnover, thus quick replacement and short training periods are required.In the latter context, it's less relevant, and the skills people acquire while doing their job are more centered around the specific domain of the company, and a lot less around the programming languages and tools they use.

author: brucehoult
author_rank: Super Contributor
timestamp: August 15, 2021, 11:57:45 pm
content: Quote from: bd139 on August 15, 2021, 05:51:07 pmWhat? I'd more than happily do that. Assuming it's a decent language I'm unfamiliar with, not something awful. Though I'll do "awful" for danger money. Having to use a weird OS on my dev machine (I care much less about the deployment machine) would be far more likely to make me refuse. Or having to clock in and out and spend defined hours in an office.

author: DiTBho
author_rank: Super Contributor
timestamp: August 16, 2021, 12:09:40 am
content: If you want a job with eRlang, you need to find a company affiliated with Ericsson.Amazon, Yahoo, WhatsUp; maybe also Mark Zuckerberg is interested to see a CV.Otherwise, it's just for personal fun and interestI have to learn Ocaml, anyway

author: bd139
author_rank: Super Contributor
timestamp: August 16, 2021, 07:50:23 am
content: Actually we've got a lot of Erlang in production (fintech). It's fairly everywhere. I am not an Erlang person though

author: tggzzz
author_rank: Super Contributor
timestamp: August 16, 2021, 08:01:37 am
content: Quote from: brucehoult on August 15, 2021, 11:57:45 pmYour caveat is important. Most home-grown domain specific languages fail that test.Too often they are the result of lazyness (don't know what we want so we'll insert a scripting language), or bad development practices (it is only a small piece of code, so we don't have to rebuild and retest the entire application), or wannabe language creator syndrome. Usually the DSLanguages are expanded incrementally until not even the creators understand everything that can happen (with conventional languages that takes decades to happen!).DSLibraries are ineveryapplication, of course. They can suffer the above problems, but at least there are tools available and the skills are transferrable to your next user of human resources (and are spotted by "AI" CV filters).

author: brucehoult
author_rank: Super Contributor
timestamp: August 16, 2021, 10:57:51 am
content: Quote from: tggzzz on August 16, 2021, 08:01:37 amI didn't think you mean N was so large it wasn't even *on* the usual lists.That's probably better, to be honest. It means the source code is probably easily available (if not already part of your check-out), and the person who made it and understands it is a co-worker. That spells a change to improve it -- perhaps reimplement it compatibly on top of a proper language, with better performance etc.

author: DiTBho
author_rank: Super Contributor
timestamp: August 16, 2021, 11:59:36 am
content: Quote from: bd139 on August 16, 2021, 07:50:23 amwhat does the company do with eRlang?fin-tech aka fin-ancial-tech-nology?There are financial languages out of there, some are written in Ocaml.I guess the C language is definitively a "no go" for those fields.

author: DiTBho
author_rank: Super Contributor
timestamp: August 16, 2021, 12:08:13 pm
content: But, can you write a firmware entirely in Ocaml? or in eRlang?

author: tggzzz
author_rank: Super Contributor
timestamp: August 16, 2021, 12:17:26 pm
content: Quote from: brucehoult on August 16, 2021, 10:57:51 amRun away, run away!Such "reimplementation" often implies that the original team has disappeared, together with the specification. The marketing team is clueless and afraid of ailienating the installed user base, so insists that youduplicatethe functions (which implies including the bugs).

author: bd139
author_rank: Super Contributor
timestamp: August 16, 2021, 12:18:12 pm
content: Stop describing my job

author: bd139
author_rank: Super Contributor
timestamp: August 16, 2021, 12:19:14 pm
content: Quote from: DiTBho on August 16, 2021, 11:59:36 amWe use C too. Although I’ve replaced most of that with Go now for architectural reasons.Erlang sits firmly in the messaging space so trade and integrations mostly.Go is starting to win there too as well though as it has some idiomatic constructs for concurrency which are easier to reason about. I’m actually working on a rough implementation of Tandem/Hp’s nonstop architecture in Go at the moment which leverages that.

author: tggzzz
author_rank: Super Contributor
timestamp: August 16, 2021, 12:28:54 pm
content: Quote from: DiTBho on August 16, 2021, 12:08:13 pmWho cares?!Can you design an X completely in Y, where X/Y aretransitors/gatesgates/asynchronous FSMsasynchronous FSMs/registersregisters/synchronous FSMssynchronous FSMs/HDLHDL/assemblerassembler/RTOSRTOS/CC/FSMsC/business rulesetc/etcThe point is to choose the abstraction which best matches your problem's description,and ignore all the irrelevant abstractions underneath that.

author: DiTBho
author_rank: Super Contributor
timestamp: August 16, 2021, 01:31:12 pm
content: Quote from: tggzzz on August 16, 2021, 12:28:54 pmOcaml comes with debug-mode, but it has no support for ICE, and without an ICE I am more fried and fried chipsTo have eRlang running as kind of "bare metal", I had to embed kernel support for "shebang", plus an eRlang virtual machine. It works, but it'san abominable thingthat doesn't allow you to write a firmware for - say - a pocket calculator.When I think about theDemiurgeas the entity responsible for fashioning and maintaining the physical universe, well it's mathematically interesting theBabyloniansinvented "water games" similar to the modern conceit of "full binary adders". They didn't know anything about the Boolean logic neither how to use the invention, and it was just entertainment, and it's interesting because it demonstrates that it is potentially possible to use *water* instead of *electrons* to build an ALU and a branch unit, which are the basic building blocks for a CPU.

author: tggzzz
author_rank: Super Contributor
timestamp: August 16, 2021, 02:10:32 pm
content: Quote from: DiTBho on August 16, 2021, 01:31:12 pmYour question was "can you write a firmware entirely in Ocaml? or in eRlang", and I answered "who cares, because...". I don't understand how your response relates to that.As for "water logic", you miss the current industrial uses of fluid logic...A simple example is the fluid logic in an automatic transmission gearbox, used to change gears.40 years ago I was asked to see whether it was worth replacing an FSM implemented in fluid logic with a microprocessor. I concluded it wasn't, since that would have required introducing electricity to an unmanned offshore gas head. That's still true today, see the rubric athttps://fluidiclogic.com/(orhttps://en.wikipedia.org/wiki/Fluidics).

author: DiTBho
author_rank: Super Contributor
timestamp: August 16, 2021, 02:25:32 pm
content: Quote from: tggzzz on August 16, 2021, 02:10:32 pmCan you write a firmware entirely in Ocaml? No, there is no ICE support, and without ICE support I cannot debug anything at the metal-bare level.Can you write a firmware entirely in eRlang? No, eRlang depends on a virtual machine to operate (in my example, I embedded one into kernel space), so you can debug things *inside* the virtual machine, but not at the metal-bare level.

author: tggzzz
author_rank: Super Contributor
timestamp: August 16, 2021, 02:39:06 pm
content: Quote from: DiTBho on August 16, 2021, 02:25:32 pmAnd with that we circle around to "who cares". You've selected justone arbitrary pairof abstraction levels in a large continuum of abstraction levels. Why not choose others?For example, why not choose business rules and HDLs? Some peopledocast business rules in FPGA logic!

author: Bassman59
author_rank: Super Contributor
timestamp: August 16, 2021, 03:27:35 pm
content: Quote from: tggzzz on August 16, 2021, 02:39:06 pmAren't the people doing business rules in FPGA logic using high-level synthesis and not writing in an HDL?

author: Bassman59
author_rank: Super Contributor
timestamp: August 16, 2021, 03:33:16 pm
content: Quote from: DiTBho on August 16, 2021, 03:14:39 pmI think it "produces good results" because we spend a lot of time verifying the small blocks. Of course we all well know that we can introduce errors when we connect the blocks together.QuoteThis is the reason for high-level synthesis tools. Rather than writing in an HDL, they take the C (or whatever) code and run it through a tool which magically converts it to the FPGA fabric. I guess it's not efficient in terms of FPGA area but the audience for this stuff has the $$$ to spend on the biggest FPGAs.That said, "business logic" is a rather wide field, so the class of problems to be solved gets narrowed.

author: tggzzz
author_rank: Super Contributor
timestamp: August 16, 2021, 05:37:49 pm
content: Quote from: Bassman59 on August 16, 2021, 03:27:35 pmI don't know: I haven't bothered to look!There are many possible approaches, all the way from coding entirely in something like System-C or the coding top level directly in an HDL. But it is worth noting that the core business rules are normally pretty simple.A typical application would bereceiving inputturning it into appropriately parameterised eventsqueueing events for processingtaking one event's parameters and deciding what to docreating a result eventtransmitting that event as outputAll except 4 would be conventionally coded in a conventional HDL.A modern HDL would be able to express 4 (i.e. the business rules) ready for synthesis.

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 16, 2021, 06:03:40 pm
content: Quote from: DiTBho on August 16, 2021, 12:08:13 pmThe "who cares" reactions to this question were fun to read, although they make a point.Trying to get back to the topic a bit, one of C's strong points is that it's indeed a language in which you an pretty much implement anything from very low-level to very high-level. Many may not find C very good for high-level abstractions, but it's still doable.Erlang runs on a virtual machine. While you could probably write your own virtual machine for using Erlang on any target, it's going to take a lot of work for any target/platform that is not readily supported. Probably no one is going to do this. Besides, even the most minimal VM for Erlang is likely to require a lot more memory than any typical MCU has. If that's the kind of target you have in mind.As to Ocaml, AFAIR, you can compile it into bytecode or into native code directly. But again here, the number of supported platforms is probably going to exclude anything like MCUs. And even native code requires a significant runtime, which you would also have to write for the specific target you wanna use. But I don't even know if there's any Ocaml compiler that supports, say, ARM-Cortex MCUs, for instance. So already good luck writing your own. (Now if that thing exists, I'll be curious to have a look.)Of course it all depends on what you call "firmware" here. Erlang can certainly be used to write "firmware". As long as the target you want to use is supported. As I said, I doubt you'll be able to use a modest MCU. But I think there are Erlang tools for PowerPC, for instance, so you could probably use it on systems hosting a PowerPC CPU and consider the software you write here "firmware".

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 16, 2021, 06:13:31 pm
content: Quote from: DiTBho on August 16, 2021, 02:25:32 pmI just answered your question, but am a bit intrigued by this reply to tggzzz you wrote here. It looks like your only points are about debugging, whereas, as I said just above, I think you'd have many other things to work out before even getting to this point.Besides, you don't "debug" code in languages such as Erlang or Ocaml the same way as you do in C. Different approach. Different mindset. Different tools. That doesn't mean those languages are not usable per se, even for writing "firmware". You seem to have an exxagerated need for low-level debugging tools. Heck, ICEs even? I think the last time I used one was over 20 years ago and that was because we were working on a very old board. As many others here (from what's being discussed on a regular basis), I even very rarely use a simple debugger for firmware development. Having one is certainly not a hard requirement for writing embedded code, and an excessive use of debuggers may be indicative of poor development methods. Just a thought, anyone can feel free to think otherwise.

author: tggzzz
author_rank: Super Contributor
timestamp: August 16, 2021, 07:51:46 pm
content: Quote from: SiliconWizard on August 16, 2021, 06:03:40 pmOf course it should be recognised that Intel has released many many virtual machines for its recent x86-64 bit ISAs.I don't mean VMs thatusethose ISAs, I mean VMs thatimplementthose ISAs. Those CISC assembler instructions are interpreted inside the processor and converted intoundocumentedmore "primitive" RISC-like microcoded instructions that are executed by the internal logic.Anybody vaguely familiar with the widely used AMD 2900 family (or intel 3000 family) of bit-slice processors will instantly recognise the concept. To coin a phrase, "plus ça change, plus c'est la même chose".https://en.wikipedia.org/wiki/AMD_Am2900https://en.wikipedia.org/wiki/Intel_3000#3000_Family

author: DiTBho
author_rank: Super Contributor
timestamp: August 17, 2021, 12:56:54 am
content: Quote from: SiliconWizard on August 16, 2021, 06:03:40 pmI know, a couple of months ago ago I implemented an eRlang virtual machine in Linux kernel space.Kind of really crazy crazy thing to do

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 17, 2021, 01:06:11 am
content: Quote from: DiTBho on August 17, 2021, 12:56:54 amOh really... so can you imagine implementing this for a target with CPU power and limited memory?

author: SiliconWizard
author_rank: Super Contributor
timestamp: August 18, 2021, 12:00:47 am
content: Maybe you can take a look at this:https://github.com/bettio/AtomVM