211 karma · joined July 2, 2023
One aspect I note is that finally the point is not having variadics or not (assuming an expression can represent a type then you can use tuples instead, which is what styx-lang does). The point is that one must have a way to *use* them.
The "consume" idiom, while working, is not great as it lead to template instances explosion. Not great but not so terrible as finally `static foreach` can only work with a kind of monomorphization too.
You dont care if in the AST some functions are doing too much. In my opinion the most important is the ability to _drive the compilation_, for example stop after lexical, stop after semantics. Then if too much code got compiled into the *.a that's unfortunate but not dramatic.
BTW there's is also the split between the driver and the frontend, but I think this is done.
I use LLVM since v9, nowadays I'm stuck on v15 (that's not because of LLVM btw).
Between the two versions there's been a radical change too, i.e "opaque pointers", but the transition was rather smooth as we were provided, for a long time, the two versions of the functions affected by the change. Maybe the LLVM team got more serious since the author experienced the said difficulties ?
Other thing I note is that the author uses the CPP API. I use the C one which exposes only a high-level subset of the CPP one. This encourages a saner use of LLVM, a more concrete separation between the front-end and the mid-end, although sometimes there are limitations.
A simple example of what encourages the C API, especially since opaque ptrs are added, is not to rely on LLVM to retrieve the IR type of an IR value. That should always be done using the AST, eg with an `.ir` field in your nodes.
Another one I remark, after a brief overview of LLVM-CRAP, is that the author had to change the internal data structure used, depending on the LLVM version [0]. Using the C API that would never had happened. The C API essentially allows to create block refs, instructions refs, value refs, type refs, contexts. Then you choose the containers you want to use to hold them. No need to switch to another stdcpp one, even if internally LLVM does so.
[0]: https://github.com/c3d/xl/blob/master/src/llvm-crap.cpp#L265
open-D is not a 4th implementation it's a fork.
worst ?
Otherwise compilation is indeed fast because it uses a system of cache (just like delphi *.dcu system) plus it has modules. On top of that we can add... context-free grammar that's fast to parse, no _insane_ preprocessing (but still some, $ifdef and co).
For a few months I had the feeling that a good switch-expression requires the bottom type... It turns out that the `assert(0)` idiom, used in a lambda, is sufficient:
var u32 a = switch b do {
1 => 2,
/* ... */
else => function(): u32 => {assert(0, "crash");}()
};
The `else` case (similar to C `default`) simply crashes the program but the type system is happy because the lambda return type is compatible.Some might think "unlikely", however this really happens. Old account are hacked and the videos, previously free, posted with that account dont play anymore unless you pay a few cents.
I did not like Vice because of that kind of things. That "fresh" aspect on first glance but you realize later that those guys are not real journalists.
They are not. They inform the reader that this system exists. Then little cherry on the cake, this system eventually leads to child labor. Plus chocolate toping, eventually someone died.
Problem of the Pascal syntax is that it prevents adoption of certain constructs, which are just not nice. A few examples
- lambda expression: `begin` ... `end`, say goodbye to nice one liners;
- binary assign: FPC has `+=` `-=` but obviously not `mod=`, `and=`, etc;
On top of that there are other things like
- shortened boolean evaluation (e.g `if someInt` => `if someInt != 0` is not possible because `and` is a two headed creature
- locals are still not default initialized
I use to like Pascal (actually Delphi then ObjFPC) much but nowaday I think the only good parts are in certain semantics, e.g no fallback in the `case`...`of` construct, manual memory management BUT ref counted arrays.
I would tend more to like a C like syntax with certain semantics coming from the Pascal world.
> Names (also called identifiers) in Lua can be any string of letters, digits, and underscores, not beginning with a digit. This coincides with the definition of names in most languages. (The definition of letter depends on the current locale: any character considered alphabetic by the current locale can be used in an identifier.)
config file being essentially KV pairs, thay means that certain property names are not valid or won't be valid if loaded by someone living in "country-with-strange-locale-istan".
> you don’t need to write destructors
I think this is not accurate. Destructors are not deallocators, they are supposed to set the object field in an invalid state. Now truth is that both are often called together, e.g `delete`.
> Typically arena lifetime is the whole program, so you don’t need to worry about freeing it
A technic I use is to increment a counter on `arena.alloc` and decrement it on `arena.dealloc`, and then free the memory (if it's on the heap) accordingly.
That's actually expected when capturing by reference.
I think a good variable name is more important, if that avoids the not-exp nice, but that's secondary.