Communities

Writing
Writing
Codidact Meta
Codidact Meta
The Great Outdoors
The Great Outdoors
Photography & Video
Photography & Video
Scientific Speculation
Scientific Speculation
Cooking
Cooking
Electrical Engineering
Electrical Engineering
Judaism
Judaism
Languages & Linguistics
Languages & Linguistics
Software Development
Software Development
Mathematics
Mathematics
Christianity
Christianity
Code Golf
Code Golf
Music
Music
Physics
Physics
Linux Systems
Linux Systems
Power Users
Power Users
Tabletop RPGs
Tabletop RPGs
Notifications
Mark all as read
Code Reviews

BMPL: The language I'll bring to life

+3
−1

Last year, I started working on a language I named SuperCode but then decided BMPL (Builder's Multi-Purpose Language) as the final name. The language would be written using C and up until now, the GitHub repo only consists of a library of functions.

I decided to bring up the language onto Codidact's chat and have even started using it as some programming language, where I'd access the functions and assign them in TIO. To this day, I'd continue making answers on Code Golf CD using the language which is, until now, a library of libraries.

For this review, I want to know anything that can be improved with the functions and what could be fixed from what I made. I'm certain all functions I made before 2021 (all libraries except time.h and is_type.h) work properly ever since I tested them.

Here's the most commonly-used function I have:

#define say(X) printf(_Generic((X),   \
                        double: "%f", \
                        float:  "%f", \
                        char *: "%s", \
                        int:    "%d"  \
                ), (X));
Why does this post require moderator attention?
You might want to add some details to your flag.
Why should this post be closed?

1 comment thread

Expected library usage? (2 comments)

1 answer

+7
−0

First of all, I realize that this is mostly a library you've implemented while learning programming, for the sake of learning, which is great. So I would rather not put a "wet blanket" over your attempts of coding and coming up with libraries, keep on doing that!

However, I hope you realize that as C libraries go, this one is quite naive. There's a long way to go until it reaches something close to a commercial production-quality library by/for professional programmers. Writing such libs is very qualified work and one needs many years of C programming experience for that.


General concerns

  • No header/include guards. This is mandatory for all header files, particular library ones. See https://stackoverflow.com/questions/7109964/creating-your-own-header-file-in-c

  • It is not recommended to place function definitions or variable declarations in headers. Especially not when you have no include guards. This will cause all manner of linking head aches and also in some cases multiple functions with the same name existing in different translation units. (The rare exception is static inline functions but I'd ignore those for now.)

    All of these functions should have a prototype function declaration only in the header (for example convert.h), then the corresponding definition in a convert.c file which includes the header.

  • Headers are supposed to come with at least some function use documentation in the form of comments. What are the parameters for, how should they be used, what will the function return, how does it handle errors etc.

basic.h

  • Your use of _Generic doesn't address qualifiers. For example const int. There was a language ambiguity how to deal with qualifiers when _Generic was released, so gcc and clang ended up implementing them differently. This was fixed in C17 - now _Generic expressions are assumed to work like "lvalue conversion", where qualifiers are discarded (though not pointed-at-type qualifiers).

    For this reason I'd recommend to either document that the code expects C17 to work correctly, or to use some macros checking __STDC_VERSION__ and changing the code accordingly.

  • Function-like macros should not end with semicolon. I expect to use the macro as say(123); not say(123).

  • It's recommended to check the result of scanf to get rugged code.

  • take_int doesn't work. You need to return the result somewhere. Decent compilers will warn against the bug scanf("%i", result);, missing &.

convert.h

  • Making wrapper functions for something as trivial as casting isn't a good idea. Code such as char ch = (char)val; is already the most readable form. Inventing some alternative syntax char ch = make_char(val); only serves two purposes: confusing other C programmers and potentially making the program perform worse.

    Always assume that the user of a library is a C programmer who already knows C.

  • make_str is problematic since returning a pointer to a local static buffer isn't safe in multi-threaded environments - it is not "thread-safe". So it might create more problems than it solves.

is_type.h

  • Again, we should assume that the user of the library knows C. But they do not yet know your library. Providing functions that are nothing but wrappers around standard C library functions is very bad practice - all it achieves is to force people to learn an alternative syntax when they already know C and already know how to use ctype.h. And potentially these functions will not get inlined by an optimizing compiler either, so they are potentially just causing function call overhead bloat.

    The same problems exist in multiple of these headers. Unfortunately these remarks render large portions of your libs useless, but please trust me on this: do not attempt to re-invent the C language. Standardization exists for a reason. If you'd go ahead and do something like that in a professional setting, you would find yourself in some serious trouble.

mathematics.h

  • power doesn't work correctly in case y is 0.

  • square_root I'm not sure if this works as expected, though why only provide one for fixed point?

memory.h

  • free doesn't return anything so I'm not sure how you managed to get this code compiling.

str.h

  • add_str could do with a name like cat_str or concat_str etc. Adding two strings together is known as string concatenation (hence the name strcat in the std lib).

  • You have no error handling in case malloc runs out of memory.

  • compare_str forgot const correctness for the 1st parameter.

  • copy_str could be improved in many ways for efficiency (a real standard lib implementation will look extremely different), but one easy thing to do is to restrict qualify the pointers. This tells the compiler that it can assume that the pointers don't point at overlapping memory and therefore give it a chance to produce slightly more efficient code:

    char *copy_str(char* restrict dest, const char* restrict src)
    
  • get_length forgot const correctness. Same remark for most of these functions.

  • The lowercase and uppercase functions contain needless checks since tolower/toupper are already guaranteed to do these checks. Converting the input to unsigned char is a good idea however, since that rules out various nasty bugs.

Why does this post require moderator attention?
You might want to add some details to your flag.

3 comment threads

Regarding recreation (6 comments)
This won't be a library for long. (1 comment)
This answer put me into a "wet blanket". Yep, I peed my pants reading what I should be fixing. I'll g... (3 comments)

Sign up to answer this question »